[BZOJ4522] [CQOI2016] 密钥破解 - Pollard-Rho - exgcd

本文介绍了一种非对称加密算法的密钥生成过程,并提出了一种利用Pollard-Rho质因数分解算法破解该加密算法的方法。通过质因数分解找到私钥,进而实现密文的解密。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

4522: [Cqoi2016]密钥破解

Time Limit: 10 Sec   Memory Limit: 512 MB
Submit: 459   Solved: 223
[ 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<N

Output

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

Sample Input

3 187 45

Sample Output

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

HINT

Source

[ Submit][ Status][ Discuss]

由于使用了大量的快速加导致我的程序非常慢 - -(不过容错性强?雾

这里首先讲一讲Pollard-Rho质因数分解算法。这里首先要了解一个叫生日悖论的东西:每23个人中有人生日在同一天的概率大于50%

因此我们可以考虑拓展应用,同理,如果我们在n以内选择一个数p,选择k个数a1,a2……ak,存在|ai-aj|=p的概率为P,当k趋于sqrt(n)级别时,P>1/2

但是遗憾的是,如果我们一组组枚举,时间复杂度没有丝毫改善,并且要耗费内存所无法存储的空间,这时候Pollard-Rho算法就派上用场了,这里我们借助一个神奇的函数f(x)=x^2+a mod n,令xi+1=f(xi),同时考虑求gcd(|xi+1-xi|,n),当其不为1或n时即为n的因子。

但是有的时候会出现环 = = 所以我们可以用Floyd的一个办法:一个a的更新满足a=f(a),而一个b的更新满足b=f(f(b)),显然当a追赶上b时就出现环了,返回寻找失败。

这样计算下去,时间复杂度是均摊的,由于long long会爆炸,我的这一部分的时间复杂度是的。

然后显然我们将N质因数分解之后,再用快速加在扩欧里到处乱搞即可 = =,时间复杂度

总时间复杂度

#include"bits/stdc++.h"
using namespace std;
typedef long long ll;
static unsigned long long seed;
const unsigned int MOD=2147483659ll;
inline unsigned long long RAND(){
	srand(seed); ll re=seed*rand()%MOD+1;
	seed=(rand()%MOD*seed+re+seed%233)%MOD+1;
	return re*rand()%MOD+1;
}
#define myrand(mod) (RAND()%mod+1)
#define f(x) ((ksc(x,x,n)+1)%n)
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll ABS(ll x){return x>0?x:-x;}
inline ll ksc(ll a,ll b,ll mo){
	a%=mo,b%=mo;ll re=0;
	while(a){
		if(a%2)re=(re+b)%mo;
		b=(b+b)%mo;a>>=1;
	}
	return re;
}
inline ll find(ll n,ll x0){
	ll a=f(x0),b=f(f(x0)),p;
	while(a!=b){
		p=gcd(ABS(a-b),n);
		if(p>1)return p==n?-1:p;
		a=f(a);b=f(f(b));
	}
	return -1;
}
inline ll Pollard_Rho(ll n){
	ll p=-1;
	for(;p==-1;p=find(n,myrand(n-1)));
	return p;
}
ll ksm(ll a,ll b,ll mo){
	ll re=1;
	while(b){
		if(b%2)re=ksc(re,a,mo);
		a=ksc(a,a,mo);b>>=1;
	}
	return re;
}
void exgcd(ll a,ll b,ll&x,ll&y,ll mo){
	if(b==0){x=1,y=0;return;}
	exgcd(b,a%b,y,x,mo);
	y=(y-ksc(a/b,x,mo)+mo)%mo;
}
ll e,N,c,d,n,r;
int main(){
	cin>>e>>N>>c;ll p=Pollard_Rho(N),y;
	r=(p-1)*(N/p-1);exgcd(e,r,d,y,r);
	n=ksm(c,d,N);printf("%lld %lld\n",d,n);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值