2242: [SDOI2011]计算器
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 5618 Solved: 2193
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,P为质数,1<=T<=10。
Sample Output
【样例输出1】
2
1
2
【样例输出2】
2
1
0
解析:
三个模板。。。
操作一:快速幂
操作二:扩展欧几里得
操作三:BSGS
代码:
#include <bits/stdc++.h>
#include <tr1/unordered_map>
#define int long long
using namespace std;
using namespace std::tr1;
const int mod=1e6+7;
int a,b,p,t,flag,gcd,x,y;
inline int get_int()
{
int x=0,f=1;
char c;
for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
if(c=='-') f=-1,c=getchar();
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return x*f;
}
inline void print(int x)
{
if(x>9) print(x/10);
putchar('0'+x%10);
}
inline int solve1(int a,int b,int p)
{
int ans=1;
while(b)
{
if(b&1) ans=(ans*a)%p;
b>>=1;
a=(a*a)%p;
}
return ans;
}
inline int exgcd(int a,int b)
{
if(!b) x=1,y=0,gcd=a;
else
{
exgcd(b,a%b);
int t=x;
x=y;
y=t-a/b*x;
}
}
inline void solve2()
{
exgcd(a,p);
if(b%gcd) {cout<<"Orz, I cannot find x!\n";return;}
x=(x*(b/gcd)%p+p)%p;
print(x),putchar('\n');
}
inline int BSGS()
{
unordered_map<int,int>Hash;
int t=(int)sqrt(p)+1;
for(int i=0;i<t;i++)
{
int val=b*solve1(a,i,p)%p;
Hash[val]=i;
}
a=solve1(a,t,p);
if(!a) return !b ? 1 : -1;
for(int i=1;i<=t;i++)
{
int val=solve1(a,i,p);
int j=Hash.find(val) == Hash.end() ? -1 : Hash[val];
if(j>=0 && i*t-j>=0) return i*t-j;
}
return -1;
}
inline void solve3()
{
int ans=BSGS();
if(!(~ans)) {cout<<"Orz, I cannot find x!\n";return;}
else print(ans),putchar('\n');
}
signed main()
{
t=get_int(),flag=get_int();
if(flag==1) for(int i=1;i<=t;i++) a=get_int(),b=get_int(),p=get_int(),print(solve1(a,b,p)),putchar('\n');
if(flag==2) for(int i=1;i<=t;i++)
{
a=get_int(),b=get_int(),p=get_int();
solve2();
}
if(flag==3) for(int i=1;i<=t;i++)
{
a=get_int(),b=get_int(),p=get_int();
solve3();
}
return 0;
}