P2485 [SDOI2011]计算器(快速幂+扩欧+bsgs)
Posted zhangbuang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2485 [SDOI2011]计算器(快速幂+扩欧+bsgs)相关的知识,希望对你有一定的参考价值。
题目描述
你被要求设计一个计算器完成以下三项任务:
1、给定y、z、p,计算y^z mod p 的值;
2、给定y、z、p,计算满足xy ≡z(mod p)的最小非负整数x;
3、给定y、z、p,计算满足y^x ≡z(mod p)的最小非负整数x。
为了拿到奖品,全力以赴吧!
输入输出格式
输入格式:输入文件calc.in 包含多组数据。
第一行包含两个正整数T、K,分别表示数据组数和询问类型(对于一个测试点内的所有数
据,询问类型相同)。
以下T 行每行包含三个正整数y、z、p,描述一个询问。
输出格式:输出文件calc.out 包括T 行.
对于每个询问,输出一行答案。
对于询问类型2 和3,如果不存在满足条件的,则输出“Orz, I cannot find x!”。
输入输出样例
说明
设问题给的是 a ,b p;
k==1 谁都会吧 = =
k=2: 扩展欧几里得 设d=(a,p) ,若d !| b 无解,
当d=1; 套班子,在0到p-1上有一个解
当d!=1, 套板子,最后设 t = b/d,也即是b是gcd的几倍,然后由于x和y算出来是除了d的,所以最后x要乘t,在0到p/d-1上有一个解
k=3 出门左转,EXBSGS
1 #include"bits/stdc++.h"
2 using namespace std;
3 typedef long long ll;
4
5 ll work1(ll a,ll b,ll mod)
6 {
7 ll ans=1;ll base=a%mod;
8 while (b){if(b&1)ans=(ans*base)%mod;b>>=1;base=base*base%mod;}return ans;
9 }
10
11 void exgcd(ll &x,ll &y,ll a,ll b)
12 {
13 if(b==0){x=1,y=0;return ;}
14 exgcd(x,y,b,a%b);ll t=x; x=y;y=(t-(a/b)*y);
15 }
16
17 unordered_map <ll,ll> mp;
18
19
20
21
22 ll bsgs(ll a,ll b,ll p)
23 {
24 b%=p;
25 if(b==1)return 0; ll d; ll k=1; int cnt=0;
26
27 while ((d=__gcd(a,p))^1)
28 {
29 if(b%d)return -1;
30 b/=d; p/=d;cnt++;
31 k=1ll*k*(a/d)%p;
32 if(k==b)return cnt;
33
34 // cout<<k<<" "<<a<<" "<<b<<" "<<p<<endl;
35 }
36
37
38
39 int m=sqrt(p)+1; ll kt=1;
40 mp.clear();
41 for (int i=0;i<m;i++)
42 {
43 mp[1LL*kt*b%p]=i;
44 kt=kt*a%p;
45
46 }
47
48 k=k*kt%p;
49
50 for (int i=1;i<=m;i++)
51 {
52 if(mp.find(k)!=mp.end()) return i*m-mp[k]+cnt;
53 k=k*kt%p;
54 }
55
56 return -1;
57
58 }
59
60
61
62
63 int main()
64
65 {
66 /* int x,y;
67 exgcd(x,y,3,10);
68 cout<<(x%10+10)%10;*/
69
70
71
72
73 ll T,k; ll y,z,p;
74 cin>>T>>k;
75
76 while (T--)
77 { scanf("%lld%lld%lld",&y,&z,&p);
78 if(k==1)
79 {
80 printf("%lld
",work1(y,z,p));
81 }
82 else if(k==2)
83 {
84 ll Gcd=__gcd(y,p); if(z%Gcd!=0)
85 {puts("Orz, I cannot find x!");continue;}
86 ll x1,y1; ll t=z/Gcd;
87 exgcd(x1,y1,y,p);
88 p=p/Gcd;
89 // cout<<x1<<endl;
90 printf("%lld
",1ll*((x1*z/Gcd)%p+p)%p);
91 }
92 else
93 {
94 ll ans=bsgs(y,z,p);
95 if(ans!=-1)printf("%lld
",ans);
96 else puts("Orz, I cannot find x!");
97 }
98 }
99
100 }
以上是关于P2485 [SDOI2011]计算器(快速幂+扩欧+bsgs)的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ2242SDoi2011计算器 快速幂+EXGCD+BSGS
BZOJ 2242 [SDOI2011]计算器(快速幂+Exgcd+BSGS)