蒟蒻哪里有什么总结,只能点击%YL%html
还有这位ZigZagK大佬的blogc++
模板题:洛谷P3846 [TJOI2007]可爱的质数ui
给定\(a,b\)和模数\(\mbox{YL}\),求\(a^x\equiv b(\bmod\mbox{YL})\)中\(x\)的最小非负整数解。保证\(\gcd(a,\mbox{YL})=1\)。spa
设\(k=\lceil\sqrt{\mbox{YL}}\rceil\),令\(x=ky-c\)(\(y\in[1,k],c\in[0,k)\),故分解惟一).net
因而有\(a^{ky}\equiv ba^c(\bmod\mbox{YL})\)code
两边的取值都只有\(k\)种,枚举右边丢进map,再枚举左边查找一下便可获得最小的解。htm
复杂度\(O(\sqrt{\mbox{YL}}\log\sqrt{\mbox{YL}})\)。注意特判掉一些特殊状况。blog
#include<bits/stdc++.h> #define LL long long #define RG register #define R RG int using namespace std; map<int,int>c; inline LL qpow(RG LL b,R k,RG LL YL){//快速幂 RG LL a=1; for(;k;k>>=1,b=b*b%YL) if(k&1)a=a*b%YL; return a; } int main(){ R a,b,YL; cin>>YL>>a>>b; if((b%=YL)==1)return puts("0"),0;//特判×2 if((a%=YL)==0)return puts("no solution"),0; R k=sqrt(YL)+1,y; RG LL p,pw=qpow(a,k,YL); for(p=b,y=0;y<k;++y,(p*=a)%=YL)//预处理 c[(int)p]=y; for(p=pw,y=1;y<=k;++y,(p*=pw)%=YL)//查找 if(c.count((int)p))return(cout<<(LL)k*y-c[(int)p]<<endl),0; return puts("no solution"),0;//找不到 }
模板题:洛谷P4195 Spoj3105 Mod
双倍经验:洛谷SP3105 MOD - Power Modulo Invertedci
能够解决\(\gcd(a,\mbox{YL})\neq1\)的状况,核心思想是试探性地约去\(\gcd\)。get
同余方程\(a^x\equiv b(\bmod\mbox{YL})\),能够提一个\(a\)出来改为不定方程\(a\cdot a^{x-1}+\mbox{YL}\cdot y=b\),等于说暂时把\(a^{x-1}\)当作了未知数。
设\(g=\gcd(a,\mbox{YL})\),学完exgcd以后咱们就知道了若是\(g\nmid b\)则方程组无解。不然就能够约成\(\frac a g\cdot a^{x-1}+\frac{\mbox{YL}}g\cdot y=\frac b g\)
咱们把约简后的方程看做一个新的不定方程\(a'\cdot a^{x-1}+\mbox{YL}'\cdot y=b'\),若是\(\gcd(a,\mbox{YL}')\)仍是不为\(1\)的话,咱们就再从幂里面拿出一个\(a\)和\(\mbox{YL}'\)约。如此循环。
终于在约了\(cnt\)次后,咱们获得了一个\(\gcd=1\)的方程了,变回来就是\(a'\cdot a^{x-cnt}\equiv b'(\bmod\mbox{YL}')\)
接下来的解法已经属于常规\(\mbox{BSGS}\)了,不过由于一些细节上的区别仍是再写一遍。
仍然设\(k=\lceil\sqrt{\mbox{YL}'}\rceil\),令\(x=ky-c\)(\(y\in[1,k],c\in[0,k)\))
因而有\(a'\cdot a^{ky}\equiv ba^{cnt}\cdot a^c(\bmod\mbox{YL}')\),其实只是恒等号两边多乘了点东西而已。
约分多出来的复杂度是\(O(\log^2\mbox{YL})\),由于最多被约\(\log\)次,它的阶小于根号就忽略掉了。又要注意一些特判。
#include<bits/stdc++.h> #define LL long long #define RG register #define R RG int using namespace std; map<int,int>c; inline LL qpow(RG LL b,R k,RG LL YL){ RG LL a=1; for(;k;k>>=1,b=b*b%YL) if(k&1)a=a*b%YL; return a; } int gcd(R x,R y){ return y?gcd(y,x%y):x; } int main(){ R a,b;RG LL YL; cin>>a>>YL>>b; while(a||b||YL){ R x=-1,a1=1,cnt=0,g,k,y,p,pw; a%=YL; if((b%=YL)==1){x=0;goto L;}//这个特判上面提过 while((g=gcd(a,YL))!=1){ if(b%g)goto L;//无解充要条件 ++cnt;b/=g;YL/=g; a1=a/g*(LL)a1%YL; if(a1==b){x=cnt;goto L;} }//注意这个特判,此时等价于a^{x-cnt}≡1(mod YL) c.clear();//多组数据注意清空 k=sqrt(YL)+1;//常规BSGS过程 pw=qpow(a,k,YL); p=b*qpow(a,cnt,YL)%YL; for(y=0;y<k;++y,p=(LL)p*a%YL) c[p]=y; p=(LL)a1*pw%YL;//多乘一个a1 for(y=1;y<=k;++y,p=(LL)p*pw%YL) if(c.count(p)){x=k*y-c[p];break;} L:~x?printf("%d\n",x):puts("No Solution"); cin>>a>>YL>>b; } return 0; }