Time Limit: 10 Sec
Memory Limit: 512 MB
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”之间有一个空格。
题目分析
裸的快速幂+EXGCD+BSGS
扩展欧几里得—推导及应用
BSGS算法
#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
#include<map>
using namespace std;
typedef long long lt;
lt read()
{
lt f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
int T,opt;
map<int,int> hash;
map<int,bool> vis;
lt qpow(lt a,lt k,lt p)
{
lt res=1;
while(k>0)
{
if(k&1)res=(res*a)%p;
a=(a*a)%p;
k>>=1;
}
return res;
}
lt exgcd(lt a,lt b,lt &x,lt &y)
{
if(b==0){x=1;y=0;return a;}
lt g=exgcd(b,a%b,x,y);
lt tp=x;
x=y; y=tp-a/b*y;
return g;
}
lt BSGS(lt a,lt b,lt p)
{
hash.clear(); vis.clear();
lt t=sqrt(p); b%=p;
for(int j=0;j<=t;++j)
{
lt tt=b*qpow(a,j,p)%p;
hash[tt]=j; vis[tt]=true;
}
a=qpow(a,t,p);
if(a==0)return b==0?1:-1;
for(int i=0;i<=t;++i)
{
lt tt=qpow(a,i,p);
if(vis[tt]){
int j=hash[tt];
if(j>=0&&i*t-j>=0) return i*t-j;
}
}
return -1;
}
int main()
{
T=read();opt=read();
while(T--)
{
lt a=read(),b=read(),p=read();
if(opt==1)printf("%lld\n",qpow(a,b,p));
else if(opt==2)
{
lt x,y,c=b;
lt g=exgcd(a,p,x,y),bg=p/g;
if(c%g!=0) printf("Orz, I cannot find x!\n");
else printf("%lld\n",(x*(c/g)%bg+bg)%bg);
}
else if(opt==3)
{
lt ans=BSGS(a,b,p);
if(ans==-1) printf("Orz, I cannot find x!\n");
else printf("%lld\n",ans);
}
}
return 0;
}