[模板] BSGS
BSGS是一种解决一类专门的问题的解法,主要是解决已知A, B, C,求X使得A^x = B (mod p)这一类问题。
解法很简单,先设x = i*m-j(m=ceil(sqrt(p))),然后进行变形,得到ai*m = b*aj (mod p)。
先枚举j (范围0-m) ,将 b*aj 存入hash表。再枚举i (范围1-m) ,从hash表中寻找第一个满足ai*m = b*aj (mod p)。
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<map> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(register int i = a;i <= n;i++) #define lv(i,a,n) for(register int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } map <ll,int> mp; ll t,m,n,ans,now; ll p,a,b; bool flag; ll qpow(ll a,ll b) { ll sum = 1; while(b) { if(b % 2 == 1) { sum *= a; } a *= a; sum %= p; a %= p; b >>= 1; } return sum; } int main() { while(~scanf("%lld%lld%lld",&p,&a,&b)) { if(a % p == 0) { printf("no solution\n"); continue; } mp.clear(); m = ceil(sqrt(p)); flag = false; now = b % p; mp[now] = 0; for(int i = 1;i <= m;i++) { now = (now * a) % p; mp[now] = i; } t = qpow(a,m); now = 1; duke(i,1,m) { now = (now * t) % p; if(mp[now]) { flag = true; ans = i * m - mp[now]; printf("%lld\n",(ans % p + p) % p); break; } } if(!flag) printf("no solution\n"); } return 0; }
只想找一个不会伤害我的人