【题解】[SDOI2011]计算器
[SDOI2011]计算器
题目描述
你被要求设计一个计算器完成以下三项任务:
- 给定 y , z , p y,z,p y,z,p,计算 y z m o d p y^z \bmod p yzmodp 的值;
- 给定 y , z , p y,z,p y,z,p,计算满足 x y ≡ z ( m o d p ) xy \equiv z \pmod p xy≡z(modp) 的最小非负整数 x x x;
- 给定 y , z , p y,z,p y,z,p,计算满足 y x ≡ z ( m o d p ) y^x \equiv z \pmod p yx≡z(modp) 的最小非负整数 x x x。
为了拿到奖品,全力以赴吧!
输入格式
输入文件包含多组数据。
第一行包含两个正整数 T , K T,K T,K,分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同)。
以下 T T T 行每行包含三个正整数 y , z , p y,z,p y,z,p,描述一个询问。
输出格式
输出文件包括 T T T 行。
对于每个询问,输出一行答案。
对于询问类型 2 和 3,如果不存在满足条件的,则输出 Orz, I cannot find x!
。
样例 #1
样例输入 #1
3 1
2 1 3
2 2 3
2 3 3
样例输出 #1
2
1
2
样例 #2
样例输入 #2
3 2
2 1 3
2 2 3
2 3 3
样例输出 #2
2
1
0
样例 #3
样例输入 #3
4 3
2 1 3
2 2 3
2 3 3
2 4 3
样例输出 #3
0
1
Orz, I cannot find x!
0
提示
测试点共分为三类,各类测试点占总测试点的比例如下:
K = K= K= | 测试点占比 |
---|---|
1 1 1 | 20 % 20\% 20% |
2 2 2 | 35 % 35\% 35% |
3 3 3 | 45 % 45\% 45% |
所有数据均满足: 1 ≤ y , z , p ≤ 1 0 9 1 \leq y,z,p \leq 10^9 1≤y,z,p≤109, p p p 是质数, 1 ≤ T ≤ 10 1 \leq T \leq 10 1≤T≤10。
大步小步+快速幂+费马小定理板题
费马小定理:A^(p-1)=1(mod p)。所以A^(p-2)即为逆元。
#include<bits/stdc++.h>
using namespace std;
long long t,k;
long long y,z,p;
map<long long,long long>mp;
long long ksm(long long x,long long y){
long long r=1;
while(y){
if(y&1){
r=r*x%p;
}
x=x*x%p;
y>>=1;
}
return r;
}
long long bsgs(){
mp.clear();
long long m=ceil(sqrt(p));
long long k=1,l=1;
for(long long i=1;i<=m;i++){
k=k*y%p;
mp[k*z%p]=i;
}
for(long long i=1;i<=m;i++){
l=l*k%p;
if(mp[l]){
return i*m-mp[l];
}
}
return -1;
}
long long exgcd(long long a,long long b,long long &x,long long y){
if(!b){
x=1;
y=0;
return a;
}else{
long long r=exgcd(b,a%b,x,y);
long long t=x;
x=y;
y=t-(a/b)*y;
return r;
}
}
int main(){
scanf("%lld%lld",&t,&k);
if(k==1){//求快速幂
while(t--){
scanf("%lld%lld%lld",&y,&z,&p);
printf("%lld\n",ksm(y,z));
}
}else if(k==2){
while(t--){
scanf("%lld%lld%lld",&y,&z,&p);
if(__gcd(y,p)!=1){
printf("Orz, I cannot find x!\n");
}else{
printf("%lld\n",z*ksm(y,p-2)%p);
}
}
}else{//大步小步
while(t--){
scanf("%lld%lld%lld",&y,&z,&p);
if(y%p==z%p){
printf("1\n");
continue;
}
long long x=bsgs();
if(x<=0)printf("Orz, I cannot find x!\n");
else printf("%lld\n",x);
}
}
}
-------------------------------------------
个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!