SDOI2011计算器

2242: [SDOI2011]计算器

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 1274  Solved: 491
[Submit][Status]

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

题解:这一题考了几个基本的数论算法,1不用多说,2扩展欧几里得求逆元也不多说。

至于3吗,我做这题以前是不知道的,后来才明白这玩意叫做离散对数,查了资料学会了这个东西(我有多弱!!!)

求a^x=b(mod n) 的最小的x的算法(shank的大步小步算法)

令m为n^0.5

我们可以求出a^0,a^1,a^2...a^(m-1) mod n 的值,记为e0,e1,e2,em-1,用map将它们存下来(为了方便之后查询,对每个ei存下它对应的最小的下标i)

求出a^m模n的逆元v

那么如果a^(k*m+0),a^(k*m+1),a^(k*m+2)...a^(k*m+m-1)模m余b(k从0到m-1),等价于

a^0=b*(v^(k*m))(mod n)

a^1=b*(v^(k*m))(mod n)

...

a*(m-1)=b*(v^(k*m))(mod n)

这样我们只要枚举k,然后在map中查询b*(v^(k*m))是否存在,若存在,用它在map中对应的i得到答案k*m+i。

这样做的时间复杂度是O(n^0.5log(n))考虑到题目数据最多十组,应该不会超时。

 1 #include <iostream>
 2 #include <cmath>
 3 #include <map>
 4 using namespace std;
 5 typedef long long LL;
 6 int T,k;
 7 LL mul_mod(LL a,LL b,LL n){
 8     return a*b%n;
 9 }
10 LL pow_mod(LL a,LL p,LL n){
11     if (p==0) return 1;
12     LL ans=pow_mod(a,p/2,n);
13     ans=ans*ans%n;
14     if (p&1) ans=ans*a%n;
15     return ans;
16 }
17 LL gcd(LL a,LL b){
18     return (b==0)?a:(gcd(b,a%b));
19 }
20 void exgcd(LL a,LL b,LL &x,LL &y){
21     if (b==0) {x=1;y=0;return ;}
22     else {exgcd(b,a%b,y,x);y=y-(a/b)*x;}
23 }
24 LL inv(LL a,LL n){
25     LL x,y;
26     exgcd(a,n,x,y);
27     return (x+n)%n;
28 }
29 LL log_mod(LL a,LL b,LL n){
30     LL m,v,e=1,i;
31     m=((int)sqrt(n)) +1;
32     if (gcd(a,n)!=1) return -1;
33     v=inv(pow_mod(a,m,n),n);
34     map <int,int> x;
35     x[1]=0;
36     for (i=1;i<m;i++){
37         e=mul_mod(e,a,n);
38         if (!x.count(e)) x[e]=i;
39     }
40     for (i=0;i<m;i++){
41         if (x.count(b)) return i*m+x[b];
42         b=mul_mod(b,v,n);
43     }
44     return -1;
45 }
46 int main(){
47     cin>>T>>k;
48     LL y,z,p,t;
49     while (T--){
50         cin>>y>>z>>p;
51         switch (k) {
52             case 1:
53                 cout<<pow_mod(y,z,p)<<endl; break;
54             case 2:{
55                 LL g=gcd(y,p);
56                 if (z%g!=0) cout<<"Orz, I cannot find x!"<<endl;
57                     else {
58                             y/=g;p/=g;z/=g;
59                             cout<<mul_mod(inv(y,p),z%p,p)<<endl;
60                     }
61                 break;
62             }
63             case 3:if ((t=log_mod(y,z,p))==-1) cout<<"Orz, I cannot find x!"<<endl;
64                 else cout<<t<<endl;
65             break;
66         }
67     }
68     return 0;
69 }
时间: 2024-10-12 15:07:03

SDOI2011计算器的相关文章

bzoj2242: [SDOI2011]计算器.

2242: [SDOI2011]计算器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 4353  Solved: 1679[Submit][Status][Discuss] 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)的最小非负整数. In

BZOJ 2242: [SDOI2011]计算器( 快速幂 + 扩展欧几里德 + BSGS )

没什么好说的... --------------------------------------------------------------------- #include<cstdio> #include<cmath> #include<map> using namespace std; typedef long long ll; int MOD; void gcd(int a, int b, int& d, int& x, int& y)

P2485 [SDOI2011]计算器

P2485 [SDOI2011]计算器 题目描述 你被要求设计一个计算器完成以下三项任务: 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.L,分别表示数据组数和询问类型(对于一个测试点内的所有数 据,询问类型相同). 以下T 行每

【bzoj2242】[SDOI2011]计算器

2242: [SDOI2011]计算器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 3207  Solved: 1258[Submit][Status][Discuss] 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)的最小非负整数. In

【bzoj2242】[SDOI2011]计算器 数论相关(快速幂+扩展欧几里得+BSGS)

2242: [SDOI2011]计算器 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 2529 Solved: 1003 [Submit][Status][Discuss] 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)的最小非负整数. In

[bzoj2242][Sdoi2011]计算器_exgcd_BSGS

计算器 bzoj-2242 Sdoi-2011 题目大意:裸题,支持快速幂.扩展gcd.拔山盖世 注释:所有数据保证int,10组数据. 想法:裸题,就是注意一下exgcd别敲错... ... 最后,附上丑陋的代码... ... #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <ma

【BZOJ 2242】[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 对于每个询问,输出一行答案.对

bzoj 2242 [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 对于每个询问,输出一行答案.对

BZOJ_2242_[SDOI2011]计算器_快速幂+扩展GCD+BSGS

题意: 你被要求设计一个计算器完成以下三项任务: 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)的最小非负整数. 分析: 各种板子题 代码: // luogu-judger-enable-o2 // luogu-judger-enable-o2 #include <stdio.h> #include <string.h> #include &