BSGS算法
BSGS算法
Ax≡B(%C) 已知A、B、C 求x
题意应该很好理解。
设x=i*m-j 这样就有A(i*m-j)≡B(%C) Aj*B≡A(i*m)(%C)
枚举j,范围0~m 将Aj*B的值存下来
枚举i,范围1~m 第一个满足Aj×B=A(m*i) (mod C)时的i*m-j即为所求。
当然此时有可能是负值,所以记得特殊处理一下,
还要一个问题没有解决,m的值如何确定?
ceil(C)是m的上限,为什么?
费马小定理:a(p-1)≡1(%p) p是质数,a,p互质,这里的p就相当于本题中的C
同时很容易得到a(k mod p-1)≡ak(mod p)的公式
k mod p-1就是k-m(p-1),原式就变成了ak-m(p-1)≡ak(mod p),即ak/am(p-1)≡ak (mod p)
得到:am(p-1)≡1(mod p)。所以 a(k mod p-1)≡ak(mod p)
所以:如果枚举x的话枚举到p即可。
所以使im−j<=p,即m=ceil(C),i,j最大值也为m。
省选有02,用map相当方便
#include<cstdio> #include<map> #include<cmath> using namespace std; int a,b,c; map<long long,int>mp; long long ksm(long long p) { long long t=1,s=a; while(p) { if(p&1) t=(t*s)%c; p>>=1; s=s*s%c; } return t; } int main() { scanf("%d %d %d",&a,&b,&c); int m=ceil(sqrt(c)),t=b%c,ans; mp[t]=0; for(int i=1;i<=m;i++) { t=(t*a)%c; mp[t]=i; } int x=ksm(m); t=1; for(int i=1;i<=m;i++) { t=(t*x)%c; if(mp[t]) { ans=i*m-mp[t]; printf("%d",(ans%c+c)%c); break; } } return 0; }