B2242 [SDOI2011]计算器
这个题就是把三个数论基础合在了一起,算是一道比较全面的题.
1的时候就是快速幂
2的时候是exgcd求逆元,特殊的,只有两数互质才有逆元.
3就是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”之间有一个空格。
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<map> #include<cstring> using namespace std; #define duke(i,a,n) for(register int i = a;i <= n;i++) #define lv(i,a,n) for(register int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) #define int long long const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } int t,k; map <int,int> mp; void work1(int y,int z,int p) { int tot = 1; while(z) { if(z & 1) { tot *= y; tot %= p; } y *= y; y %= p; z >>= 1; } printf("%lld\n",tot); } int exgcd(int a,int b,int &x,int &y) { if(b == 0) { x = 1; y = 0; return a; } int t = exgcd(b,a % b,y,x); y -= (a / b * x); return t; } void work2(int y,int z,int p) { int x,f; // z %= p; int d = exgcd(y,p,x,f); if(d != 1) { printf("Orz, I cannot find x!\n"); return; } x = (x % p + p) % p; x = (x * z) % p; /*if(now == p) printf("Orz, I cannot find x!"); else*/ printf("%lld\n",x); } int qpow(int a,int b,int p) { int tot = 1; while(b) { if(b & 1) { tot *= a; tot %= p; } a *= a; a %= p; b >>= 1; } return tot; } void work3(int a,int b,int p) { if(a % p == 0) { printf("Orz, I cannot find x!\n"); return; } mp.clear(); int m = ceil(sqrt(p)); int now = b % p,ans; mp[now] = 0; duke(i,1,m) { now = (now * a) % p; mp[now] = i; } int t = qpow(a,m,p); now = 1; int ok = 1; duke(i,1,m) { now = (now * t) % p; if(mp[now]) { ans = i * m - mp[now]; printf("%lld\n",(ans % p + p) % p); ok = 0; break; } } if(ok == 1) printf("Orz, I cannot find x!\n"); } main() { read(t);read(k); //cout<<t<<endl; duke(i,1,t) { int y,z,p; read(y);read(z);read(p); if(k == 1) { work1(y,z,p); } else if(k == 2) { work2(y,z,p); } else if(k == 3) { work3(y,z,p); } //cout<<i<<" "<<t<<endl; } return 0; }
只想找一个不会伤害我的人