BZOJ2242SDoi2011计算器 快速幂+EXGCD+BSGS
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2242SDoi2011计算器 快速幂+EXGCD+BSGS相关的知识,希望对你有一定的参考价值。
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
HINT
Source
Solution:第一问快速幂
第二问EXGCD
第三问BSGS
BSGS(Baby Step Giant Step)网上介绍的很详细了,但是我令x=im-j这样就不用求逆元辣,相应的为了不出现负数是i从1开始到m枚举,则j从1到m枚举,因为可以等于m,j就不需要从0开始啦.。
另:一开始在CV上测,用了puts试试,忘了自带换行在CV上过了,然而在BZOJ PE了233
1 2 #include <iostream> 3 #include <cstdio> 4 #include <cmath> 5 #include <map> 6 #define ll long long 7 using namespace std; 8 ll y,z,p; 9 10 ll fast_pow(ll y,ll z,ll p) 11 { 12 ll ans=1; 13 while (z) 14 { 15 if (z&1) ans=ans*y%p; 16 y=y*y%p; 17 z>>=1; 18 } 19 return ans; 20 } 21 22 ll gcd(ll a,ll b) 23 {return b==0?a:gcd(b,a%b);} 24 25 void ex_gcd(ll a,ll b,ll &x,ll &y) 26 { 27 if (!b) {x=1;y=0;return;} 28 ex_gcd(b,a%b,x,y); 29 ll t=x; x=y; y=t-a/b*y; 30 } 31 32 void solve1() 33 { 34 printf("%lld\n",fast_pow(y,z,p)); 35 } 36 37 void solve2() 38 { 39 ll d=gcd(y,p); 40 if (z%d) {printf("Orz, I cannot find x!\n");return;} 41 y/=d; z/=d; 42 ll a,b; 43 ex_gcd(y,p,a,b); 44 a=a*z%p; 45 while (a<0) a+=p; 46 printf("%lld\n",a); 47 } 48 49 void solve3() 50 { 51 y%=p,z%=p; 52 if (!y && !z) {puts("1"); return;} 53 if (!y) {printf("Orz, I cannot find x!\n");return;} 54 map<ll,ll> mp; 55 mp.clear(); 56 ll m=ceil(sqrt(p)); 57 ll t=fast_pow(y,m,p),k=z%p;//直接m即可 58 for (int i=0;i<m;i++) 59 { 60 if (!mp[k]) if (i) mp[k]=i;//注意变量,及时订正。 61 else mp[k]=-1; 62 k=k*y%p; 63 } 64 k=1; 65 for (int i=0;i<m;i++) 66 { 67 if (mp[k])//注意!mp与mp的判断 68 { 69 if (mp[k]==-1) mp[k]=0; 70 printf("%lld\n",i*m-mp[k]); 71 return; 72 } 73 k=k*t%p; 74 } 75 printf("Orz, I cannot find x!\n");//各种傻 76 } 77 78 int main() 79 { 80 int T,t; 81 scanf("%d%d",&T,&t); 82 while (T--) 83 { 84 scanf("%lld%lld%lld",&y,&z,&p); 85 if (t==1) solve1(); 86 if (t==2) solve2(); 87 if (t==3) solve3(); 88 } 89 }
以上是关于BZOJ2242SDoi2011计算器 快速幂+EXGCD+BSGS的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ_2242_[SDOI2011]计算器_快速幂+扩展GCD+BSGS
[bzoj2242][Sdoi2011]计算器_exgcd_BSGS