tip:
bsgs用来求解形如 $B^L == N(mod P)$ 的式子(求解 $L$ )。
实战:
T1:Discrete Logging(板子)
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<map> 5 #define ll long long 6 using namespace std; 7 ll a,b,mod,m,ans,s,judge; 8 map< ll,int > v; 9 inline ll qpow(ll a,ll x,ll sum=1){ 10 for(;x;x>>=1,a=a*a%mod) if(x&1) sum=sum*a%mod; 11 return sum; 12 } 13 signed main(){ 14 while(~scanf("%lld%lld%lld",&mod,&a,&b)){ 15 v.clear(); 16 if(a%mod==0){ puts("no solution"); continue; } 17 m=sqrt(mod)+1; ans=b%mod; 18 for(register int i=1;i<=m;++i){ ans=(ans*a)%mod; v[ans]=i; } 19 s=qpow(a,m); ans=1; judge=0; 20 for(register int i=1;i<=m;++i){ 21 ans=(ans*s)%mod; 22 if(v[ans]){ 23 ll t=(i*m-v[ans]+mod)%mod; 24 printf("%lld ",(i*m%mod-v[ans]+mod)%mod); 25 judge=1; break; 26 } 27 } 28 if(judge==0) puts("no solution"); 29 } 30 }
T2:计算器
题干:
你被要求设计一个计算器完成以下三项任务:
1、给定y,z,p,计算 $Y^Z mod P $ 的值;
2、给定y,z,p,计算满足 $ xy ≡ Z ( mod P ) $的最小非负整数;
3、给定y,z,p,计算满足 $ Y^x ≡ Z ( mod P) $的最小非负整数。
Code:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<map> 5 #define ll long long 6 using namespace std; 7 ll m,n,k,t,x,T,y,z,mod; 8 inline int qpow(ll a,ll x,ll mod,ll sum=1){ 9 for(;x;x>>=1,a=a*a%mod) if(x&1) sum=sum*a%mod; 10 return sum; 11 } 12 inline ll exgcd(ll a,ll b,ll &x,ll &y){ 13 if(b==0){ x=z/a; y=0; return a; } 14 ll ans=exgcd(b,a%b,y,x); 15 y-=a/b*x; 16 return ans; 17 } 18 inline void bsgs(ll a,ll b,ll mod){ 19 //printf("%lld %lld %lld ",a,b,mod); 20 map< ll,ll > v; 21 if(a%mod==0){ puts("Orz, I cannot find x!"); return; } 22 ll maxx=sqrt(mod)+1,judge=0,s=qpow(a,maxx,mod),ans=b%mod; 23 for(register int i=1;i<=maxx;++i) ans=(ans*a)%mod, v[ans]=i; 24 ans=1; 25 for(register int i=1;i<=maxx;++i){ 26 ans=(ans*s)%mod; 27 if(v[ans]){ 28 printf("%lld ",(i*maxx%mod-v[ans]+mod)%mod); 29 judge=1; break; 30 } 31 } 32 if(judge==0) puts("Orz, I cannot find x!"); 33 } 34 inline void work(){ 35 scanf("%lld%lld%lld",&y,&z,&x); 36 if(k==1) printf("%d ",qpow(y,z,x)); 37 if(k==2){ 38 ll xx,yy,gcd=exgcd(y,x,xx,yy); 39 if(z%gcd) puts("Orz, I cannot find x!"); 40 else{ 41 xx%=x; 42 (xx<0)?printf("%lld ",xx+x):printf("%lld ",xx); 43 } 44 } 45 if(k==3) bsgs(y,z,x); 46 } 47 signed main(){ 48 scanf("%lld%lld",&T,&k); 49 while(T--) work(); 50 }
T3:Matrix
题干:
给定矩阵 A , B 和模数 p ,求最小的 x 满足 $A^x = B (mod p)$,数据保证在p内有解
题解:
这道题就是注意矩阵定义时注意重载运算符 < 。
Code:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<map> 6 #define $ 72 7 using namespace std; 8 int m,n,mod; 9 struct tree{ 10 int a[$][$]; 11 tree(){ memset(a,0,sizeof(a)); } 12 friend bool operator < (tree aa,tree bb){ 13 for(register int i=1;i<=n;++i) 14 for(register int j=1;j<=n;++j){ 15 if(aa.a[i][j]!=bb.a[i][j]) return aa.a[i][j]<bb.a[i][j]; 16 } 17 return 0; 18 } 19 friend tree operator * (tree aa,tree bb){ 20 tree sum=tree(); 21 for(register int i=1;i<=n;++i) 22 for(register int j=1;j<=n;++j) 23 for(register int k=1;k<=n;++k) 24 sum.a[i][j]=(sum.a[i][j]+aa.a[i][k]*bb.a[k][j])%mod; 25 return sum; 26 } 27 friend tree operator ^ (tree aa,int x){ 28 tree sum=tree(); 29 for(register int i=1;i<=n;++i) sum.a[i][i]=1; 30 for(;x;x>>=1,aa=aa*aa) if(x&1) sum=sum*aa; 31 return sum; 32 } 33 }A,B; 34 map< tree,int > v; 35 inline void bsgs(){ 36 int maxx=sqrt(mod)+1; 37 tree ans=B,s=A^maxx; 38 for(register int i=1;i<=maxx;++i) ans=ans*A, v[ans]=i; 39 for(register int i=1;i<=n;++i) ans.a[i][i]=1; 40 ans=tree(); 41 for(register int i=1;i<=n;++i) ans.a[i][i]=1; 42 for(register int i=1;i<=maxx;++i){ 43 ans=ans*s; 44 if(v[ans]) printf("%d ",(i*maxx%mod-v[ans]+mod)%mod), exit(0); 45 } 46 puts("Orz Orz Orz Orz Orz Orz Orz Orz Orz Orz"); 47 } 48 signed main(){ 49 scanf("%d%d",&n,&mod); 50 for(register int i=1;i<=n;++i) 51 for(register int j=1;j<=n;++j) scanf("%d",&A.a[i][j]); 52 for(register int i=1;i<=n;++i) 53 for(register int j=1;j<=n;++j) scanf("%d",&B.a[i][j]); 54 bsgs(); 55 }