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。

Sample Output

【样例输出1】
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 }

 

posted @ 2017-09-14 21:26  wfj_2048  阅读(123)  评论(0编辑  收藏  举报