bzoj2242 [SDOI2011]计算器
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
正解:快速幂+$exgcd$+$BSGS$。
现在才会$BSGS$,我觉得我要被初三的小学弟超过了。。
其实还是比较简单的,就是利用了分块的思想,把$a^{x}$拆成$a^{m*i-j}$,其中$m=\sqrt{p}$取上整。
移项以后可以得到$a^{m*i}=b*a^{j}$,于是预处理出$a^{j}$,然后枚举$i$就行了。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 6 using namespace std; 7 8 map <ll,ll> mp; 9 10 il ll gi(){ 11 RG ll x=0,q=1; RG char ch=getchar(); 12 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 13 if (ch=='-') q=-1,ch=getchar(); 14 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 15 return q*x; 16 } 17 18 il ll qpow(RG ll a,RG ll b,RG ll p){ 19 RG ll ans=1; 20 while (b){ 21 if (b&1) ans=ans*a%p; 22 a=a*a%p,b>>=1; 23 } 24 return ans; 25 } 26 27 il ll exgcd(RG ll a,RG ll b,RG ll &x,RG ll &y){ 28 if (!b){ x=1,y=0; return a; } 29 RG ll t=exgcd(b,a%b,y,x); y-=a/b*x; return t; 30 } 31 32 int main(){ 33 #ifndef ONLINE_JUDGE 34 freopen("calc.in","r",stdin); 35 freopen("calc.out","w",stdout); 36 #endif 37 RG ll T=gi(),k=gi(); 38 if (k==1){ 39 while (T--){ 40 RG ll a=gi(),b=gi(),p=gi(); 41 printf("%lld\n",qpow(a,b,p)); 42 } 43 } 44 if (k==2){ 45 while (T--){ 46 RG ll a=gi(),b=gi(),p=gi(),x,y; a%=p,b%=p; 47 RG ll t=exgcd(a,p,x,y); while (x<0) x+=p; 48 if (b%t) puts("Orz, I cannot find x!"); 49 else printf("%lld\n",x*(b/t)%p); 50 } 51 } 52 if (k==3){ 53 while (T--){ 54 RG ll a=gi(),b=gi(),p=gi(),m=ceil(sqrt(p)); 55 a%=p,b%=p; if (!a && !b){ puts("1"); continue; } 56 if (!a){ puts("Orz, I cannot find x!"); continue; } 57 mp.clear(); RG ll am=qpow(a,m,p),fg=0; 58 for (RG ll i=0,t=b;i<m;++i,t=t*a%p) mp[t]=i; 59 for (RG ll i=1,x=am;i*i<=p+1;++i,x=x*am%p) 60 if (mp.count(x)){ printf("%lld\n",i*m-mp[x]),fg=1; break; } 61 if (!fg) puts("Orz, I cannot find x!"); 62 } 63 } 64 return 0; 65 }