BZOJ_2242_[SDOI2011]计算器_快速幂+扩展GCD+BSGS
BZOJ_2242_[SDOI2011]计算器_快速幂+扩展GCD+BSGS
题意:
你被要求设计一个计算器完成以下三项任务:
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)的最小非负整数。
分析:
各种板子题
代码:
// luogu-judger-enable-o2 // luogu-judger-enable-o2 #include <stdio.h> #include <string.h> #include <algorithm> #include <map> #include <math.h> using namespace std; #define LL long long map<LL,int> mp; LL qp(LL x,LL y,LL mod){ LL re=1; while(y){ if(y&1ll)re=re*x%mod; x=x*x%mod; y>>=1ll; } return re; } void exgcd(LL a,LL b,LL &x,LL &y,LL &p){ if(!b){x=1;y=0;p=a;return ;} exgcd(b,a%b,y,x,p); y-=(a/b)*x; } LL BSGS(LL n,LL a,LL b){ if(n==1)if(!b)return a!=1; else return -1; if(b==1)if(a)return 0; else return -1; if(a%n==0)if(!b)return 1; else return -1; LL m=ceil(sqrt(n)),d=1,base=1; mp.clear(); for(int i=0;i<m;i++) { if(!mp.count(base))mp[base]=i; base=(base*a)%n; } for(int i=0;i<m;i++) { LL x,y,s; exgcd(d,n,x,y,s); x=(x*b%n+n)%n; if(mp.count(x))return i*m+mp[x]; d=(d*base)%n; } return -1; } int main() { int t,k; scanf("%d%d",&t,&k); int i; LL a,b,n,x,y,p; for(i=1;i<=t;i++){ scanf("%lld%lld%lld",&a,&b,&n); if(k==1){ printf("%lld\n",qp(a,b,n)); }else if(k==2){ exgcd(a,n,x,y,p); if(b%p){ puts("Orz, I cannot find x!");continue; } x=(x*(b/p)%n+n)%n; printf("%lld\n",x); }else if(k==3){ LL x=BSGS(n,a,b); if(x==-1)puts("Orz, I cannot find x!"); else printf("%lld\n",x); } } }