bzoj 2242: [SDOI2011]计算器

Description

你被要求设计一个计算器完成以下三项任务:
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)的最小非负整数。

Solution

打个 \(BSGS\) 板子
\(x=a*m-b\)
原式变为 \(y^{a*m}=z*y^b\,\,(mod P)\)
枚举 \(b=[0,m-1]\) 求出所有的取值,并存下来
再枚举 \(a\) ,查找右边是否有出现过,由欧拉定理: \(a\) 不会超过 \(\frac{P}{m}\)
\(y\%P==0\) 时且 \(P>1\) 时无解,特判一下
\(m=sqrt(P)\) 时,复杂度最优

#include<bits/stdc++.h>
#define int long long
using namespace std;
int mod;
inline int qm(int x,int k){
    int sum=1;
    while(k){
        if(k&1)sum=1ll*sum*x%mod;
        x=1ll*x*x%mod;k>>=1;
    }
    return sum;
}
inline int exgcd(int a,int b,int &x,int &y){
    if(!b){x=1;y=0;return a;}
    int r=exgcd(b,a%b,y,x);y-=a/b*x;
    return r;
}
inline void solo(int a,int b,int c){
    int x,y,r;
    r=exgcd(a,b,x,y);
    if(c%r){puts("Orz, I cannot find x!");return ;}
    x*=c/r;b/=r;
    x=(x%b+b)%b;
    cout<<x<<endl;
}
//y^x=z (mod P)
map<int,int>a;
inline void bsgs(int y,int z){
    y%=mod;z%=mod;
    if(z==1){puts("0");return ;}
    if(y%mod==0){
        if(mod>1)puts("Orz, I cannot find x!");
        else puts("0");
        return ;
    }
    a.clear();
    int t=sqrt(mod),e=qm(y,t);
    for(int i=0;i<t;i++,z=1ll*z*y%mod)a[z]=i;
    for(int i=1,x=e;i<=t+1;i++,x=1ll*x*e%mod)
        if(a.find(x)!=a.end()){cout<<i*t-a[x]<<endl;return ;}
    puts("Orz, I cannot find x!");
}
main(){
  freopen("pp.in","r",stdin);
  freopen("pp.out","w",stdout);
  int T,K,y,z;
  cin>>T>>K;
  while(T--){
      cin>>y>>z>>mod;
      if(K==1)cout<<qm(y,z)<<endl;
      else if(K==2)solo(y,mod,z);
      else bsgs(y,z);
  }
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/Yuzao/p/8977753.html