BSGS
(BSGS()(Baby) (Step) (Gaint) (Step)),大步超大步小步算法,是求高次同余方程最小正整数解的一种常用算法。通常被用于求解形如使方程 (a^x equiv y (mod) (p)) ((p) ⊥ (a) )成立的最小 (x)。
(BSGS) 算法的实现过程类似数学中的缩放法,将待求的指数 (x) 化为 (a sqrt p + b),通过枚举 (a) 来求解。
具体过程如下:
一:
(large a^x equiv y (mod) (large p))
(large a^{ klceil frac x k ceil-(klceil frac x k ceil-x)}equiv y (mod) (large p)) (large (k=lceil sqrt p ceil))
(large {(a^k)}^n*a^{-m} equiv y (mod) (large p)) (large (n=lceil frac x k ceil,m=klceil frac x k ceil-x))
(large {(a^k)}^n equiv inv_{(a^{-m})}*y=a^{m}*y)
二:
设 (large k=lceil sqrt p ceil),(x=n*k-m),(nin [1,k)),(min [1,k))
则求 (large {(a^k)}^n equiv inv_{(a^{-m})}*y=a^{m}*y)
于是我们便可以从前往后枚举 (m) 以 (y*(a^m)modp) 为下标,(m) 为值存入一个 (map) 中(预处理),再枚举 (n) ,若存在 (map[{(a^k)}^n]),则 (x=n*k-map[{(a^k)}^n]).
复杂度 (O(sqrt p log p))
Code:
//P3846
#include<bits/stdc++.h>
using namespace std;
int p,x,y,k,n,a;
map<int,int>M;
int qp(int x,int y){
int s=1;
while(y){if(y&1)s=1ll*s*x%p;x=1ll*x*x%p;y>>=1;}
return s;
}
int main(){
cin>>p>>a>>y;
int k=ceil(sqrt(p));n=y;
for(int i=0;i<k;i++){ //预处理
M[n]=i;
n=1ll*n*a%p;
}
int t=qp(a,k);x=1;
for(int i=1;i<=k;i++){ //枚举答案
x=1ll*x*t%p;
if(M.count(x)){printf("%d
",i*k-M[x]);return 0;}
}
puts("no solution");return 0;
}