【bzoj2242】[SDOI2011]计算器
2242: [SDOI2011]计算器
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 3207 Solved: 1258
[Submit][Status][Discuss]
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)的最小非负整数。
Input
输入包含多组数据。
第一行包含两个正整数T,K分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同)。
以下行每行包含三个正整数y,z,p,描述一个询问。
Output
对于每个询问,输出一行答案。对于询问类型2和3,如果不存在满足条件的,则输出“Orz, I cannot find x!”,注意逗号与“I”之间有一个空格。
Sample Input
【样例输入1】
3 1
2 1 3
2 2 3
2 3 3
【样例输入2】
3 2
2 1 3
2 2 3
2 3 3
【数据规模和约定】
对于100%的数据,1<=y,z,p<=10^9,为质数,1<=T<=10。
3 1
2 1 3
2 2 3
2 3 3
【样例输入2】
3 2
2 1 3
2 2 3
2 3 3
【数据规模和约定】
对于100%的数据,1<=y,z,p<=10^9,为质数,1<=T<=10。
Sample Output
【样例输出1】
2
1
2
【样例输出2】
2
1
0
2
1
2
【样例输出2】
2
1
0
【吐槽】
三合一的一道模板题。快速幂+扩展gcd+离散对数
学过这三个的人应该都会吧,不会的。。。传送门:http://www.cnblogs.com/chty/p/6022641.html
写的时候手贱把哈希表写错了,调了半天。。。
贴个丑陋的代码:
1 /************* 2 bzoj 2242 3 by chty 4 2016.11.9 5 *************/ 6 #include<iostream> 7 #include<cstdio> 8 #include<cstdlib> 9 #include<cstring> 10 #include<ctime> 11 #include<cmath> 12 #include<algorithm> 13 using namespace std; 14 #define FILE "read" 15 #define MAXN 99991 16 typedef long long ll; 17 struct node{ll v,f,num;}hash[MAXN+10]; 18 ll a,b,mod; 19 inline ll read() 20 { 21 ll x=0,f=1; char ch=getchar(); 22 while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();} 23 while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} 24 return x*f; 25 } 26 void insert(ll v,ll x) 27 { 28 ll temp=v%MAXN; 29 while(hash[temp].f&&hash[temp].v!=v) {temp++; if(temp>MAXN) temp-=MAXN;} 30 if(!hash[temp].f) hash[temp].f=1,hash[temp].v=v,hash[temp].num=x; 31 } 32 ll find(ll v) 33 { 34 ll temp=v%MAXN; 35 while(hash[temp].f&&hash[temp].v!=v) {temp++; if(temp>MAXN) temp-=MAXN;} 36 if(!hash[temp].f) return -1; 37 else return hash[temp].num; 38 } 39 ll gcd(ll a,ll b) {return !b?a:gcd(b,a%b);} 40 ll exgcd(ll a,ll b,ll &x,ll &y) 41 { 42 if(!b) {x=1; y=0; return a;} 43 ll g=exgcd(b,a%b,x,y); 44 ll t=x;x=y;y=t-a/b*y; 45 return g; 46 } 47 void solve1(){ll sum=1;for(;b;b>>=1,a=a*a%mod)if(b&1)sum=sum*a%mod;printf("%d\n",sum);} 48 void solve2() 49 { 50 ll x,y,d=exgcd(a,mod,x,y); 51 if(b%d) {printf("Orz, I cannot find x!\n");return;} 52 ll t=mod/d; 53 while(x<0) x+=t; 54 while(x>=t) x-=t; 55 printf("%lld\n",x*b%mod); 56 } 57 void solve3() 58 { 59 if(mod==1) {puts("0"); return;} 60 a%=mod;b%=mod; 61 ll ret(1); 62 for(ll i=0;i<=50;i++) {if(ret==b) {printf("%lld\n",i); return; ret=ret*a%mod;}} 63 ll temp,ans(1),cnt(0); 64 while((temp=gcd(a,mod))!=1) 65 { 66 if(b%temp) {printf("Orz, I cannot find x!\n");return;} 67 mod/=temp; b/=temp; 68 ans=ans*(a/temp)%mod; 69 cnt++; 70 } 71 ll m=(ll)sqrt(mod*1.0),t(1); 72 for(ll i=0;i<m;i++) {insert(t,i);t=t*a%mod;} 73 for(ll i=0;i<m;i++) 74 { 75 ll x,y; 76 exgcd(ans,mod,x,y); 77 ll val=x*b%mod; 78 val=(val+mod)%mod; 79 ll j=find(val); 80 if(j!=-1) {printf("%lld\n",i*m+j+cnt);return;} 81 ans=ans*t%mod; 82 } 83 printf("Orz, I cannot find x!\n"); 84 return; 85 } 86 void pre() {for(ll i=0;i<=MAXN;i++)hash[i].f=0,hash[i].num=hash[i].v=-1;} 87 int main() 88 { 89 freopen(FILE".in","r",stdin); 90 freopen(FILE".out","w",stdout); 91 ll T=read(),flag=read(); 92 while(T--) 93 { 94 pre(); 95 a=read(); b=read(); mod=read(); 96 switch(flag) 97 { 98 case 1:solve1();break; 99 case 2:solve2();break; 100 case 3:solve3();break; 101 } 102 } 103 return 0; 104 }