题目链接:

​http://poj.org/problem?id=2447​


题目大意:

RSA是个有名的公匙密码系统。在这个系统中,每个参与者有一个只能自己知道的私匙和一个每个人都

知道的公匙。为了安全地把信息传递给对方,应该用公匙对信息进行加密,对方用自己的私匙进行解密。

对RSA系统的描述如下:
首先,选择两个大素数P、Q,计算N = P * Q。

然后,选择一个正整数E作为加密密匙,令T = (p-1)*(q-1),且gcd(E,T) = 1。
最后,计算解密密匙D,使得(E * D) mod T = 1,这里D是E模T的逆元。

公匙表示为{E,N},私匙表示为{D,N},P和Q被舍弃。

加密数据的过程为
C = M^E mod N
解密数据的过程为
M = C^D mod N

M是一个比N小的非负整数成为明文,C是密文。
现在问题来了:给你密文C和公匙{E,N},能找到明文M吗?


思路:

因为N是一个大整数,先用PollardRho对N做大整数的数分解,得到一个素因子P,那么另一个素因子

Q = N/Q,这样得到了两个素数p和q。再求出T = (P-1)*(Q-1)。然后用扩展欧几里得的方法求出E关于

模T的逆元D。根据公匙M = C^D mod N,从而得到明文。


AC代码:


#include<iostream>
#include<algorithm>
#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#define LL long long
using namespace std;

LL mod_mul(LL x,LL y,LL mo)
{
LL t;
x %= mo;
for(t = 0; y; x = (x<<1)%mo,y>>=1)
if(y & 1)
t = (t+x) %mo;

return t;
}
//LL mod_mul(LL x,LL y,LL mo)
//{
// LL t,T,a,b,c,d,e,f,g,h,v,ans;
// T = (LL)(sqrt(double(mo)+0.5));
// t = T*T - mo;
// a = x / T;
// b = x % T;
// c = y / T;
// d = y % T;
// e = a*c / T;
// f = a*c % T;
// v = ((a*d+b*c)%mo + e*t) % mo;
// g = v / T;
// h = v % T;
// ans = (((f+g)*t%mo + b*d)% mo + h*T)%mo;
// while(ans < 0)
// ans += mo;
// return ans;
//}
LL mod_exp(LL num,LL t,LL mo)
{
LL ret = 1, temp = num % mo;
for(; t; t >>=1,temp=mod_mul(temp,temp,mo))
if(t & 1)
ret = mod_mul(ret,temp,mo);

return ret;
}

//PollarRho大整数因子分解
LL gcd(LL a,LL b)
{
if(b == 0)
return a;
return gcd(b, a % b);
}

LL PollarRho(LL n, int c)
{
int i = 1;
srand(time(NULL));
LL x = rand() % (n-1) + 1;
LL y = x;
int k = 2;
while(true)
{
i++;
x = (mod_exp(x,2,n) + c) % n;
LL d = gcd(n+y-x,n);
if(1 < d && d < n)
return d;
if(y == x)
return n;
if(i == k)
{
y = x;
k *= 2;
}
}
}

void ExGCD(LL a,LL b,LL &d,LL &x,LL &y)
{
if(b == 0)
{
x = 1;
y = 0;
d = a;
}
else
{
ExGCD(b,a%b,d,y,x);
y -= x*(a/b);
}
}

int main()
{
LL p,q,t,c,e,n;
while(cin >> c >> e >> n)
{
p = PollarRho(n,10007);
q = n/p;
t = (p-1)*(q-1);
LL d,x0,y0;
ExGCD(e,t,d,x0,y0);
x0 = (x0%t + t) % t;
cout << mod_exp(c,x0,n) << endl;
}
return 0;
}