標籤:baby_step
http://poj.org/problem?id=2417
A^x = B(mod C),已知A,B,C,求x。
這裡C是素數,可以用普通的baby_step。
在尋找最小的x的過程中,將x設為i*M+j。從而原始變為A^M^i * A^j = B(mod C),D = A^M,那麼D^i * A^j = B(mod C ),
預先將A^j存入hash表中,然後枚舉i(0~M-1),根據擴充歐幾裡得求出A^j,再去hash表中尋找相應的j,那麼x = i*M+j。
確定x是否有解,就是在迴圈i的時候判斷相應A^j是否有解,而且最小的解x一定在(0~C-1),因為gcd(D^i,C) = 1.
如果(0~C-1)無解,那麼一定無解。因為A^x%C(C是素數)有迴圈節,A^x%C = A^(x%phi[c])%C,迴圈節的長度為phi(C),即C-1,x >= C以後開始新一輪的迴圈,因此(0~C-1)內無解的話,一定無解。
#include <stdio.h>#include <iostream>#include <map>#include <set>#include <list>#include <stack>#include <vector>#include <math.h>#include <string.h>#include <queue>#include <string>#include <stdlib.h>#include <algorithm>#define LL long long#define _LL __int64#define eps 1e-12#define PI acos(-1.0)using namespace std;const int maxn = 499991;bool hash[maxn+10];int idx[maxn+10];LL val[maxn+10];//插入雜湊表void insert(int id, LL vv){int v = vv % maxn;while(hash[v] && val[v] != vv){v++;if(v == maxn)v -= maxn;}if(!hash[v]){hash[v] = true;idx[v] = id;val[v] = vv;}}//尋找vv對應的jj,A^jj = vvint found(LL vv){int v = vv%maxn;while(hash[v] && val[v] != vv){v++;if(v == maxn)v -= maxn;}if(hash[v] == false)return -1;return idx[v];}void extend_gcd(LL a, LL b, LL &x, LL &y){if(b == 0){x = 1;y = 0;return;}extend_gcd(b,a%b,x,y);LL t = x;x = y;y = t-a/b*y;}/*A^x = B(mod C)令x = i*M+j, 其中M = ceil(sqrt(C*1.0)),(0 <= i,j < M)那麼原式變為A^M^i*A^j = B(mod c)先枚舉j(0~M-1),將A^j%C存入hash表中令D = A^M%C,X = A^j,那麼D^i*X = B(mod C)枚舉i(0~M-1)求得D^i設為DD,DD*X = B(mod C)DD,C已知,根據擴充歐幾裡得求出X,在hash表中尋找X對應的jj,即A^jj = X。那麼x = i*M+jj,若找不到jj無解。*/LL baby_step(LL A, LL B, LL C){memset(hash,false,sizeof(hash));memset(idx,-1,sizeof(idx));memset(val,-1,sizeof(val));LL M = ceil(sqrt(C*1.0));//將A^j存入hash表中LL D = 1;for(int j = 0; j < M; j++){insert(j,D);D = D*A%C;}//D = A^M%C,res = D^i,求方程res*X = B(mod C)中的X,去找X對應的jj,那麼x=i*M+jj.LL res = 1,x,y;for(int i = 0; i < M; i++){extend_gcd(res,C,x,y);x = x*B;x = (x%C+C)%C;int jj = found(x);if(jj != -1){return (LL)i*M+jj;}res = res*D%C;}return -1;}int main(){LL A,B,C;while(~scanf("%lld %lld %lld",&C,&A,&B)){LL res = baby_step(A,B,C);if(res == -1)printf("no solution\n");elseprintf("%lld\n",res);}return 0;}