bsgs总结

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\n",(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:

 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\n",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\n",(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\n",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\n",xx+x):printf("%lld\n",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 }
View Code

T3:Matrix

题干:

扫描二维码关注公众号,回复: 6853861 查看本文章

  给定矩阵 A , B 和模数 p ,求最小的 x 满足 $A^x = B (mod p)$,数据保证在p内有解

题解:
  这道题就是注意矩阵定义时注意重载运算符 < 。

Code:

 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\n",(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 }
View Code

猜你喜欢

转载自www.cnblogs.com/OI-zzyy/p/11235623.html