您的位置:首页 > 其它

2242: [SDOI2011]计算器

2016-09-04 13:46 169 查看

2242: [SDOI2011]计算器

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 3045  Solved: 1206

[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

[Submit][Status][Discuss]

对于询问1,快速幂解决
对于询问2,扩展欧几里得解决
对于询问3,采用BSGS算法
询问y^x≡z(mod p)的最小非负整数解x,保证p为素数
令Sqrt = sqrt(p)
则y^x = (y^Sqrt)^i*y^j
枚举i,令T = (y^Sqrt)^i
则原式化为T*y^j≡z(mod p)
用扩展欧几里得求出y^j
hash查表。。。

如果p不是素数,可以用扩展BSGS
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;

const int hash = 999983;
typedef long long LL;

int T,typ,top,s[hash],ha[hash],va[hash];

int ksm(LL x,int y,LL p)
{
LL ret = 1;
for (; y; y >>= 1) {
if (y & 1) ret = ret*x%p;
x = x*x%p;
}
return ret;
}

LL gcd(LL a,LL b,LL &x,LL &y)
{
if (!b) {
x = 1; y = 0;
return a;
}
LL ret = gcd(b,a%b,x,y);
LL tmp = x;
x = y;
y = tmp - y*(a/b);
return ret;
}

LL GCD(LL a,LL b,LL z)
{
LL x,y;
LL g = gcd(a,b,x,y);
if (z % g != 0) return -1;
x = x * z / g;
if (x < 0)
x = x % b + b;
return x % b;
}

void hash_insert(int v,int mi)
{
int posi = v%hash;
while (va[posi] != -1) {
if (va[posi] == v) return;
++posi;
}
va[posi] = v; ha[posi] = mi;
s[++top] = posi;
}

int hash_search(LL now)
{
int posi = now%hash;
for (;;) {
if (va[posi] == -1) return -1;
if (va[posi] == now) return ha[posi];
++posi;
}
}

LL Baby_step(LL t,LL p,LL z,LL Sqrt)
{
LL now = 1;
for (int i = 0; i <= Sqrt; i++) {
LL x = GCD(now,p,z);
if (x == -1) continue;
int posi = hash_search(x%p);
if (posi != -1)
return i*Sqrt + posi;
now = now*t%p;
}
return -1;
}

int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif

memset(va,-1,sizeof(va));
cin >> T >> typ;
while (T--) {
if (typ == 1) {
int x,y,p;
cin >> x >> y >> p;
printf("%d\n",ksm(x,y,p));
}
else if (typ == 2) {
int y,z,p; LL x;
cin >> y >> z >> p;
x = GCD(y,p,z);
if (x == -1) puts("Orz, I cannot find x!");
else cout << x << endl;
}
else {
int y,z,p,Sqrt,t; LL x;
cin >> y >> z >> p;
Sqrt = sqrt(p);
if (Sqrt * Sqrt < p) ++Sqrt;
int now = 1; //top = 0;
for (int i = 0; i <= Sqrt; i++)
hash_insert(now,i),now = 1LL*now*y%p;
t = ksm(y,Sqrt,p);
x = Baby_step(t,p,z,Sqrt);
if (x == -1) puts("Orz, I cannot find x!");
else cout << x << endl;
while (top) va[s[top--]] = -1;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: