bzoj4522【CQOI2016】秘钥破解

4522: [Cqoi2016]密钥破解

Time Limit: 10 Sec   Memory Limit: 512 MB
Submit: 388   Solved: 193
[ Submit][ Status][ Discuss]

Description

 一种非对称加密算法的密钥生成过程如下:
1.任选两个不同的质数p,q
2.计算N=pq,r=(p−1)(q−1)
3.选取小于r,且与r互质的整数e
4.计算整数d,使得ed≡1KQ/r
5.二元组(N,e)称为公钥,二元组(N,d)称为私钥
当需要加密消息M时(假设M是一个小于L整数,因为任何格式的消息都可转为整数表示),
使用公钥(N,e),按照n^e≡cKQ/N运算,可得到密文C。
对密文C解密时,用私钥(N,d),按照c^d≡nKQ/N运算,可得到原文M。算法正确性证明省略。
由于用公钥加密的密文仅能用对应的私钥解密,而不能用公钥解密,因此称为非对称加密算法。
通常情况下,公钥由消息的接收方公开,而私钥由消息的接收方自己持有。这样任何发送消息的
人都可以用公钥对消息加密,而只有消息的接收方自己能够解密消息。
现在,你的任务是寻找一种可行的方法来破解这种加密算法,即根据公钥破解出私钥,并据此解密密文。

Input

输入文件内容只有一行,为空格分隔的j个正整数e,N,c。N<=2^62,c

Output

输出文件内容只有一行,为空格分隔的k个整数d,n。

Sample Input

3 187 45

Sample Output

107 12
//样例中 p = 11, q = 17



数论模板的应用

Pollard-Rho算法求质因数+扩展欧几里得+快速幂+快速乘

分享一个Pollard-Rho算法的讲解:http://www.cnblogs.com/jackiesteed/articles/2019910.html

(不管你们看懂没,反正我是没看懂)




#include
#include
#include
#include
#include
#include
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
using namespace std;
ll a,c,d,e,n,p,q,r,ans;
inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
ll getmul(ll x,ll y,ll mod)
{
	ll ret=0;
	for(;y;y>>=1,x=x*2%mod) if (y&1) ret=(ret+x)%mod;
	return ret;
}
ll getpow(ll x,ll y,ll mod)
{
	ll ret=1;
	for(;y;y>>=1,x=getmul(x,x,mod)) if (y&1) ret=getmul(ret,x,mod);
	return ret;
}
ll gcd(ll x,ll y)
{
	return y?gcd(y,x%y):x;
}
void exgcd(ll x,ll y,ll &a,ll &b)
{
	if (!y){a=1;b=0;return;}
	exgcd(y,x%y,b,a);
	b-=x/y*a;
}
ll getinv(ll x,ll y)
{
	ll ret,t;
	exgcd(x,y,ret,t);
	ret=(ret%y+y)%y;
	return ret;
}
ll f(ll x)
{
	return (getmul(x,x,n)+a)%n;
}
ll pollard_rho(ll n)
{
	ll x1,x2,tmp;
	while (1)
	{
		a=rand()%100;
		x1=x2=2;
		do
		{
			x1=f(x1);x2=f(f(x2));
			tmp=gcd(abs(x2-x1),n);
			if (tmp>1) return tmp;
		}while (x1!=x2);
	}
}
int main()
{
	srand(909475573);
	e=read();n=read();c=read();
	p=pollard_rho(n);q=n/p;
	r=(p-1)*(q-1);
	d=getinv(e,r);
	ans=getpow(c,d,n);
	printf("%lld %lld\n",d,ans);
}


你可能感兴趣的:(数学,Pollard-Rho算法,OIer的狂欢)