用
B
S
G
S
BSGS
BSGS 算法可以在
O
(
n
)
O(\sqrt n)
O(n) 的时间内求出上述的同余式。
设 m = ⌈ p ⌉ m = \left\lceil\sqrt p\right\rceil m=⌈p⌉,若有解,则最小非负整数解 一定在 [ 0 , p ] [0,p] [0,p] 内,所以设 x = i × m − j x = i \times m - j x=i×m−j。
将式子变形, a i × m − j ≡ b ( m o d p ) ⇒ a i × m ≡ b × a j ( m o d p ) a^{i \times m - j} \equiv b (\mod p) \Rightarrow a^{i \times m} \equiv b \times a^j(\mod p) ai×m−j≡b(modp)⇒ai×m≡b×aj(modp)。
这样我们枚举 j j j,范围 [ 0 , m ] [0,m] [0,m],将 b × a j b \times a^j b×aj 存入哈希表。
然后枚举 i i i,范围 [ 1 , m ] [1,m] [1,m],从哈希表中寻找第一个满足 a i × m ≡ b × a j ( m o d p ) a^{i \times m} \equiv b \times a^j(\mod p) ai×m≡b×aj(modp),此时 x = i × m − j x = i \times m - j x=i×m−j 即为所求的答案。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <limits.h>
#define re register
#define int long long
#define drep(a,b,c) for(re int a(b) ; a>=(c) ; --a)
#define rep(a,b,c) for(re int a(b) ; a<=(c) ; ++a)
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch == '-') f=-1 ; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
inline void print(int x){
if(x < 0) putchar('-'),x = -x;
if(x >= 10) print(x / 10);
putchar(x % 10 + '0');
}
int p,b,n,fl,ans=LONG_LONG_MAX;
map<int,int> mp;
signed main(){
p = read(),b = read(),n = read();
int m = sqrt(p);
int mul = 1;
rep(i,0,m-1) mp[n*mul%p] = i,mul=mul*b%p;
int base = 1;
rep(i,0,m){
if(mp[base]) fl = 1,ans = min(ans,(i*m-mp[base]+p)%p);
base = base*mul%p;
}
if(fl) printf("%lld\n",ans);
else printf("no solution");
return 0;
}