P3846 [TJOI2007] 可爱的质数/【模板】BSGS 题解
BSGS本质上是一个分块算法。
我们考虑暴力求解的过程,显然答案的周期为$p$,所以我们只需要求得p之内的答案即可。
此时依然可能有多个解。
这个时候,我们只需要枚举1到p利用快速幂求值即可。
不过这太慢了,我们考虑使用分块的方法
我们把p分为$m=\sqrt p$块
我们求出每一块的端点值即$a^0,a^m,a^{2m},a^{3m}...a^{(m-1)m}$
对于每一个块的内部,我们预处理出所有可能的值,即$a^0,a^1...a^m$
枚举每一个端点值,查找端点值内部有没有某一个点能够满足原题条件。
形式化的请看oi-wiki
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<cmath>
#define int long long
using namespace std;
inline int r()
{
int s=0,k=1;char c=getchar();
while(!isdigit(c))
{
if(c=='-')k=-1;
c=getchar();
}
while(isdigit(c))
{
s=s*10+c-'0';
c=getchar();
}
return s*k;
}
int p,b,n;
int gcd(int a,int b)
{
if(!b)return a;
return gcd(b,a%b);
}
map<int,int>m;
int pw(int a,int b,int mod)
{
int base=a,ans=1;
while(b)
{
if(b&1)
{
ans*=base;
ans%=mod;
}
base*=base;
base%=mod;
b>>=1;
}
return ans;
}
signed main()
{
p=r();b=r();n=r();
int g=gcd(b,p);
if(n%g)
{
cout<<"no solution"<<endl;
return 0;
}
n/=g;p/=g;b/=g;
int s=sqrt(p)+1;
int now=1;
for(int i=1;i<=s;i++)//b^i
{
now*=b;
now%=p;
if(m.find(now)==m.end())m[now]=i;
}
for(int i=0;i<=s;i++)//根号分块 si+j
{
int tmp=pw(b,i*s,p);
tmp=pw(tmp,p-2,p);
int x=n*tmp;
x%=p;
if(m.find(x)!=m.end())
{
cout<<i*s+m[x];
return 0;
}
}
cout<<"no solution";
}
本文来自博客园,作者:lei_yu,转载请注明原文链接:https://www.cnblogs.com/lytql/p/15022944.html