擴展BSGS(學習筆記)
阿新 • • 發佈:2019-04-10
return code name article details 我們 學習筆記 new tchar
洛咕
題意:已知a,p,b,求滿足\(a^x≡b(\mod p)\)的最小的自然數x(p不一定是質數).
當p是質數的時候,我們可以直接用普通的BSGS解決.而本題中p不一定是質數,就需要用到擴展的BSGS了.
大佬談擴展BSGS
#include<bits/stdc++.h> #define LL long long using namespace std; struct su{ int x,y,p; }b[72727]; int tot,head[72727]; inline int read(){ int s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();} return s*w; } inline int gcd(int a,int b){ if(b==0)return a; return gcd(b,a%b); } inline int ksm(LL x,int y,int p){ int cnt=1; while(y){ if(y&1)cnt=(cnt*x)%p; x=(x*x)%p;y>>=1; } return cnt; } inline void hash(int x,int y){ b[++tot].x=x;b[tot].y=y;y%=72727; b[tot].p=head[y];head[y]=tot; } inline int BSGS(int x,int y,int p,int ex){ int z=sqrt(p)+1;LL sx=1,sy; for(int i=0;i<z;++i){ hash(i,sx*y%p); sx=sx*x%p; } sy=sx*ex%p;//唯一的改動,這裏需要乘ex for(int i=1;i<=z;++i,sy=sy*sx%p) for(int j=head[sy%72727];j;j=b[j].p) if(b[j].y==sy)return i*z-b[j].x; return -1; } inline int EX_BSGS(int a,int b,int p){ if(b==1)return 0;//特判b=1的情況 LL c=1,z,d;int k=0; while(1){ d=gcd(a,p); if(d==1)break;//a,p已經互質了就break掉 if(b%d)return -1;//d無法整除y,方程無解 ++k;c=c*(a/d)%p; //k記錄除了多少次,c表示的是方程的通解 b/=d;p/=d;//利用上述同余性質 if(c==b)return k; } z=BSGS(a,b,p,c); return z==-1?z:z+k; } int main(){ while(1){ int n=read(),mod=read(),m=read();tot=0; if(!n&&!m&&!mod)break; for(int i=0;i<72727;i++)head[i]=0; //多組數據初始化 int ans=EX_BSGS(n%mod,m%mod,mod); if(ans==-1)puts("No Solution"); else printf("%d\n",ans); } return 0; }
擴展BSGS(學習筆記)