[bzoj2242][SDOI2011]计算器
来自FallDream的博客,未经允许,请勿转载,谢谢。
你被要求设计一个计算器完成以下三项任务:
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)的最小非负整数。
1<=y,z,p<=10^9
第一问快速幂 第二问exgcd 第三问bsgs
然后bsgs的时候感觉写$y^{ax-b}=z$比较舒服,这样$y^b$可以直接乘到右边
#include<iostream> #include<cstdio> #include<cmath> #include<map> #define ll long long using namespace std; inline int read() { int x = 0 , f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } int n,k,y,z,p,MN; ll a,b; map<int,int> mp; int pow(int x,int k,int mod) { if(mod==1) return 0; int sum=1; for(;k;k>>=1,x=1LL*x*x%mod) if(k&1) sum=1LL*sum*x%mod; return sum; } int exgcd(int a,int b,ll&x,ll&y) { if(!b){x=1;y=0;return a;} int c=exgcd(b,a%b,x,y); ll t=x;x=y;y=t-(a/b)*x; return c; } int main() { while(scanf("%d%d",&n,&k)!=EOF) { if(k==1) { for(int i=1;i<=n;i++) y=read(),z=read(),p=read(),printf("%d\n",pow(y,z,p)); } if(k==2) { for(int i=1;i<=n;i++) { y=read(),z=read(),p=read(); int c=exgcd(y,p,a,b); if(z%c) puts("Orz, I cannot find x!"); else y/=c,z/=c,p/=c,printf("%lld\n",((a*z/c)%p+p)%p); } } if(k==3) { for(int i=1;i<=n;i++) { mp.clear(); y=read();z=read();p=read();y%=p;MN=ceil(sqrt(p)); if(!y&&!z)puts("1");else if(!y)puts("Orz, I cannot find x!"); else if(p==1) puts("0"); else { int times=pow(y,MN,p);bool flag=0; for(int j=0,k=z%p;j<=MN;j++,k=1LL*k*y%p) mp[k]=j; for(int j=1,k=times;j<MN;j++,k=1LL*k*times%p) if(mp[k]) {flag=1,printf("%lld\n",1LL*j*MN-mp[k]);break;} if(!flag) puts("Orz, I cannot find x!"); } } } } return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream