题目大意:给出A,B,C,求A^x=B(mod C)的最小x的值。
思路:著名的BSGS算法。将C拆分成根号块,先对一个根号内的东西暴力插入一个Hash表中(别问我为什么不用map,因为这个题卡map。。。
另我们要求的x=i * m + j,原式可以写成A^(i * m) * A^j = B(mod C)。这是ax=b(mod c)的形式我们只需要枚举i,然后看有没有符合要求的j就可以了。
CODE:
#define _CRT_SECURE_NO_WARNINGS #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; long long A,B,C; void EXGCD(long long a,long long b,long long &d,long long &x,long long &y) { if(!b) { d = a,x = 1,y = 0; return ; } EXGCD(b,a % b,d,y,x); y -= x * (a / b); } long long Solve(long long a,long long b,long long c) //ax = b(mod c) { long long x = 0,y = 0,d = 0; EXGCD(a,c,d,x,y); return ((x % c) + c) * b % c; } long long QuickPower(long long x,long long y) { long long re = 1; while(y) { if(y&1) re = re * x % C; x = x * x % C; y >>= 1; } return re; } struct HashSet{ #define MO 23333 int head[MO * 2 + 10],total; int next[MO * 2 + 10],f[MO * 2 + 10]; long long val[MO * 2 + 10]; void Reset() { memset(head,0,sizeof(head)); total = 0; } void Insert(long long x,int _) { int temp = x % MO; for(int i = head[temp]; i; i = next[i]) if(val[i] == x) { f[i] = min(f[i],_); return ; } next[++total] = head[temp]; val[total] = x; f[total] = _; head[temp] = total; } int Find(long long x) { int temp = x % MO; for(int i = head[temp]; i; i = next[i]) if(val[i] == x) return f[i]; return -1; } }G; int main() { while(scanf("%I64d%I64d%I64d",&C,&A,&B) != EOF) { G.Reset(); long long temp = 1,m = ceil(sqrt((double)C)); for(int i = 0; i < m; ++i) { G.Insert(temp,i); temp = temp * A % C; } bool find = false; for(int i = 0; i * m < C; ++i) { long long temp = Solve(QuickPower(A,i * m),B,C); if(G.Find(temp) != -1) { printf("%I64d\n",i * m + G.Find(temp)); find = true; break; } } if(!find) puts("no solution"); } return 0; }