Bzoj2242 [SDOI2011]计算器
2017-03-07 20:09
357 查看
Submit: 3611 Solved: 1400
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。
Sample Output
【样例输出1】2
1
2
【样例输出2】
2
1
0
HINT
Source
数学
喜闻乐见3 in 1
第一问,快速幂
第二问,扩展欧几里得
第三问,BSGS
提交上去秒WA,于是开始查BSGS的错(一般都会这么想吧),然而并没有发现错。
和黄学长的程序对拍BSGS,有那么几个数据不一样,调试无果,又找了一堆程序对拍,最后确定是黄学长写挂了233
最后发现是task2第48行,(LL)x*b写成了(LL)(x*b),大概是炸了
/*by SilverN*/ #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<vector> #include<map> #define LL long long using namespace std; const int mxn=100010; 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 ksm(int a,int k,int p){ int res=1; while(k){ if(k&1)res=((LL)res*a%p); a=((LL)a*a%p); k>>=1; } return res; } void task1(int a,int k,int p){ printf("%d\n",ksm(a,k,p)); } int gcd(int a,int b){ return (!b)?a:gcd(b,a%b); } void exgcd(int a,int b,int &x,int &y){ if(!b){x=1;y=0;return;} exgcd(b,a%b,x,y); int tmp=x;x=y;y=tmp-a/b*y; return; } void task2(int a,int b,int p){ int x,y; int tmp=gcd(a,p); if(b%tmp){ printf("Orz, I cannot find x!\n"); return; } b/=tmp;a/=tmp;p/=tmp; exgcd(a,p,x,y); x=(LL)x*b%p; while(x<0)x+=p; printf("%d\n",x); return; } map<int,int>mp; void task3(int a,int b,int p){ if(a%p==0){ if(b==0)printf("1\n"); else printf("Orz, I cannot find x!\n"); return; } mp.clear(); int m=sqrt((double)p); int tmp=1; for(int i=0;i<m;i++){ int now=((LL)tmp*b)%p; if(!mp[now])mp[now]=i; tmp=((LL)tmp*a)%p; } int res=1,ans,i; for(i=m;i<=p;i+=m){ res=(LL)res*tmp%p; if(mp[res]){ ans=i-mp[res]; break; } } if(i>p){ printf("Orz, I cannot find x!\n"); return; } printf("%d\n",ans); return; } int y,z,p; int main(){ int T,k; T=read();k=read(); int y,z,p; while(T--){ y=read();z=read();p=read(); switch(k){ case 1:{ task1(y,z,p); break; } case 2:{ task2(y,z,p); break; } case 3:{ task3(y,z,p); break; } } } return 0; }
相关文章推荐
- bzoj 2242: [SDOI2011]计算器【扩展欧几里得+快速幂+BSGS】
- 【bzoj2242】【SDOI2011】【计算器】
- 【BZOJ 2242】[SDOI2011]计算器
- 【BZOJ2242】[SDOI2011]计算器
- bzoj 2242: [SDOI2011]计算器
- BZOJ2242:[SDOI2011]计算器——题解
- 【bzoj2242】[SDOI2011]计算器 数论相关(快速幂+扩展欧几里得+BSGS)
- bzoj2242 : [SDOI2011]计算器 [BSGS算法]
- bzoj2242 [SDOI2011]计算器
- bzoj 2242 [SDOI2011]计算器(数论知识)
- BZOJ2242 [SDOI2011]计算器
- BZOJ_2242_[SDOI2011]计算器_快速幂+扩展GCD+BSGS
- 【bzoj2242】【SDOI2011】计算器
- BZOJ2242 [SDOI2011]计算器 【BSGS】
- BZOJ 2242([SDOI2011]计算器-Baby Step Giant Step第1题)
- BZOJ 2242 [SDOI2011]计算器 BSGS+高速幂+EXGCD
- bzoj2242 [SDOI2011]计算器
- BZOJ2242 [SDOI2011]计算器 【BSGS】
- 【数论】【快速幂】【扩展欧几里得】【BSGS算法】bzoj2242 [SDOI2011]计算器
- 【bzoj 2242】【SDOI2011】计算器 代码(C++)