高次同余方程
求解 \(a^x\equiv b(\mod p)\).
大步小步算法,\(BSGS(baby-step giant-step)\),要求 \(gcd(a,p)=1\),可在 \(O(\sqrt p)\) 时间复杂度内求解。
在 \(p<=10^{16}\) 时没有大问题。
方程的解满足 \(0<=x<p\).
令 \(t=\left \lceil \sqrt p \right \rceil,0<=j<t,x=i*t-j\),则 \(a^{i*t-j}\equiv b(\mod p)\).
两边同时乘上 \(a^j\) 可得,\(a^{i*t}\equiv ba^j(\mod p)\).
对于所有的 \(j\in [0,t-1]\),将 \(ba^j\) 插入 \(hash/map\) 中。
枚举所有的 \(i\in[0,t]\),查找表中是否存在 \(a^{i*t}\),若存在则可以得到对应的 \(j\) 与 \(x=i*t-j\).
inline int BSGS(int a,int b,int p){
a%=p;
b%=p;
if(b==1)return 0;
mp.clear();
int t=sqrt(p)+1,re=1;/*初值a^0*/
for(int i=0;i<t;i++)mp[re*b%p]=i,(re*=a)%=p;/*依次插入b*a^i*/
a=re;/*re=a^t%p*/
re=1;
for(int i=0;i<=t;i++){
int j=mp.find(re)==mp.end()?-1:mp[re];
if(j>=0&&i*t-j>=0)return i*t-j;
(re*=a)%=p;
}
return -1;
}
扩展BSGS算法
求解 \(a^x\equiv b(\mod p)\),\(gcd(a,p)\not=1\).
将不互质的情况转化为互质的情况,设 \(g=gcd(a,p)\),两边同时除以 \(g\).
得到,\(\frac{a^x}{g}\equiv \frac{b}{g}(\mod \frac{p}{g})\),即 \(a^{x-1}\frac{a}{g}\equiv \frac{b}{g}(\mod \frac{p}{g})\).
当 \(g\not\mid b\) 且 \(b\not=1\) 时无解。
一直递归直到 \(gcd(a,p)=1\),假设一共递归了 \(cnt\) 次,设 \(d=\prod_{i=1}^{k}g_i\).
原式即,\(a^{x-cnt}\frac{a^{cnt}}{d}\equiv \frac{b}{d}(\mod \frac{p}{g})\).
于是用 \(a,\frac{b}{g},\frac{p}{g}\) 做 \(BSGS\) ,注意还有一个系数 \(\frac{a^{cnt}}{d}\) 要乘进去,出入 \(BSGS\) 中。
inline int BSGS(int a,int b,int p,int ad){
a%=p,b%=p;
mp.clear();
int t=sqrt(p)+1,re=1;
for(int i=0;i<t;i++)mp[re*b%p]=i,(re*=a)%=p;
a=re;
re=ad;
for(int i=0;i<=t;i++){
int j=mp.find(re)==mp.end()?-1:mp[re];
if(j>=0&&i*t-j>=0)return i*t-j;
(re*=a)%=p;
}
return -1;
}
inline int exBSGS(int a,int b,int p){
a%=p;
b%=p;
if(b==1||p==1)return 0;/*特判*/
int cnt=0,g=gcd(a,p),ad=1;
while(g>1){
if(b%g)return -1;/*判断无解*/
cnt++;/*累加次数*/
b/=g;
p/=g;
(ad*=a/g)%=p;/*更新系数*/
if(ad==b)return cnt;/*ad=b则前面的一项a的指数为0,直接返回cnt*/
g=gcd(a,p);
}
int ans=BSGS(a,b,p,ad);
if(ans==-1)return -1;
return ans+cnt;
}
也可以不将系数传进去,将 \(b\) 乘上系数的逆元即可,注意用 \(exgcd\) 计算。
inline int inv(int a,int p){
int x,y;
exgcd(a,p,x,y);
return (x%p+p)%p;
}
inline int BSGS(int a,int b,int p){
a%=p,b%=p;
mp.clear();
int t=sqrt(p)+1,re=1;
for(int i=0;i<t;i++)mp[re*b%p]=i,(re*=a)%=p;
a=re;
re=1;
for(int i=0;i<=t;i++){
int j=mp.find(re)==mp.end()?-1:mp[re];
if(j>=0&&i*t-j>=0)return i*t-j;
(re*=a)%=p;
}
return -1;
}
inline int exBSGS(int a,int b,int p){
a%=p;
b%=p;
if(b==1||p==1)return 0;
int cnt=0,g=gcd(a,p),ad=1;
while(g>1){
if(b%g)return -1;
cnt++;
b/=g;
p/=g;
(ad*=a/g)%=p;
if(ad==b)return cnt;
g=gcd(a,p);
}
int ans=BSGS(a,b*inv(ad,p)%p,p);/*乘上系数的逆元*/
if(ans==-1)return -1;
return ans+cnt;
}

浙公网安备 33010602011771号