[note]BSGS & exBSGS
阿新 • • 發佈:2018-11-03
BSGS
(感覺這東西還是要寫一下)
BSGS主要用於求解形如\(x^k=y\pmod p\)(注意這裡p與x互質)這樣的方程的最小正整數解的問題
設\(m=\lceil\sqrt p\rceil,k=am-b,a\in[1,m],b\in[0,m)\)
那麼上面的方程可以變形成\(x^{am}=yx^b\pmod p\)
列舉\(b\),計算出右邊的值存到\(map\)中,列舉\(a\)查表即可
Q:可以列舉左邊存表,右邊查嘛?
A:可以,但是左邊查到表可以直接輸出...
順便一說,map裡要存最大值,這樣你算出的答案是最小的,所以能更新就更新
複雜度:\(O(\sqrt plogp)\)
模板題[TJOI2007]可愛的質數
#include<bits/stdc++.h> using namespace std; int p; map<int,int>M; int ksm(int x,int y){ int s=1; while(y){if(y&1)s=1ll*s*x%p;x=1ll*x*x%p;y>>=1;} return s; } int main(){ int x,y; cin>>p>>x>>y; int m=sqrt(p)+1; int s=y; for(int i=0;i<m;i++){ M[s]=i;//能更新就更新 s=1ll*s*x%p; } int t=ksm(x,m);s=1; for(int i=1;i<=m;i++){ s=1ll*s*t%p; if(M.count(s)){printf("%d\n",i*m-M[s]);return 0;} } puts("no solution");return 0; }
擴充套件BSGS
當p不是素數時(這時x,p不一定互質),
設d=gcd(x,p),
若d不整除y,那麼只有y=1時,x=0,其他情況均無解
若d整除y,當d=1時,直接BSGS
否則有\[x^k=y\pmod p\]
\[x^{k-1}×\frac{x}{d}=\frac{y}{d}\pmod{\frac{p}{d}}\]
繼續分解到d=1為止.
\[x^{k-t}×\frac{x^t}{\prod d_i}=\frac{y}{\prod d_i}\pmod{\frac{p}{\prod d_i}}\]
然後首先檢驗x=[0,t)是否為解,顯然t是log級別的
如果[0,t)都不是解,由於\(x,\frac{p}{\prod d_i}\)
最後記得答案加上t啊
模板題[SPOJ3105]MOD
#include<bits/stdc++.h>
using namespace std;
int re(){
int x=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
}
int p;
map<int,int>M;
void mul(int&x,int y){x=1ll*x*y%p;}
int ksm(int x,int y){
int s=1;
while(y){if(y&1)mul(s,x);mul(x,x);y>>=1;}
return s;
}
void exbsgs(int x,int y){
if(y==1){puts("0");return;}
int d=__gcd(x,p),k=1,t=0;
while(d^1){
if(y%d){puts("No Solution");return;}
++t;y/=d;p/=d;mul(k,x/d);
if(y==k){printf("%d\n",t);return;}
d=__gcd(x,p);
}
int s=y;M.clear();int m=sqrt(p)+1;
for(int i=0;i<m;i++){
M[s]=i;mul(s,x);
}
s=k;k=ksm(x,m);
for(int i=1;i<=m;i++){
mul(s,k);
if(M[s]){printf("%d\n",i*m-M[s]+t);return;}
}
puts("No Solution");
}
int main(){
int x,y;
while(1){
x=re(),p=re(),y=re();
if(!x&&!p&&!y)break;
x%=p;y%=p;
exbsgs(x,y);
}
return 0;
}