2242: [SDOI2011]计算器
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 5035 Solved: 1914
[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)的最小非负整数。
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
HINT
Source
第一轮day1
sol:
1,2问快速幂,3bsgs
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<map>
using namespace std;
typedef long long ll;
int n,m;
inline int read()
{
char c;
int res,flag=0;
while((c=getchar())>'9'||c<'0') if(c=='-')flag=1;
res=c-'0';
while((c=getchar())>='0'&&c<='9') res=(res<<3)+(res<<1)+c-'0';
return flag?-res:res;
}
int x,y,z,ty;
inline int ksm(int x,int y,int z)
{
int res=1;
while(y)
{
if(y&1) res=(ll)res*x%z;
x=(ll)x*x%z;
y>>=1;
}
return res;
}
map<int,int> hash;
inline void bsgs()
{
y%=z;
if (x==0&&y==0) {printf("1\n");return;}
if (x==0&&y!=0) {printf("Orz, I cannot find x!\n");return;}
hash.clear();
int q=ceil(sqrt(z)),p=y;
for(int j=1;j<=q;++j)
{
p=(ll)p*x%z;
if(!hash[p])
hash[p]=j;
}
p=ksm(x,q,z);
int tmp=1;
for(int i=1;i<=q;++i)
{
tmp=(ll)tmp*p%z;
if(hash[tmp])
{
printf("%d\n",i*q-hash[tmp]);
return;
}
}
printf("Orz, I cannot find x!\n");
}
inline void solve()
{
x=read();
y=read();
z=read();
x%=z;
if(ty==1) printf("%d\n",ksm(x,y,z));
else if(ty==2)
{
y%=z;
if(!x&&y) printf("Orz, I cannot find x!\n");
else printf("%d\n",(ll)y*ksm(x,z-2,z)%z);
}
else bsgs(x,y,z);
}
int main()
{
// freopen("calc.in","r",stdin);
// freopen("calc.out","w",stdout);
int T=read();
ty=read();
while(T--) solve();
}