BZOJ4522:[CQOI2016]密钥破解(Pollard-Rho,exgcd)
Description
一种非对称加密算法的密钥生成过程如下:
1. 任选两个不同的质数 p ,q
2. 计算 N=pq , r=(p-1)(q-1)
3. 选取小于r ,且与 r 互质的整数 e
4. 计算整数 d ,使得 ed≡1 mod r
5. 二元组 (N,e) 称为公钥,二元组 (N,d) 称为私钥
当需要加密消息 n 时(假设 n 是一个小于 N 整数,因为任何格式的消息都可转为整数表示),使用公钥 (N,e),按照
n^e≡c mod N 运算,可得到密文 c 。
对密文 c 解密时,用私钥 (N,d) ,按照c^d≡n mod N 运算,可得到原文 n 。
1. 任选两个不同的质数 p ,q
2. 计算 N=pq , r=(p-1)(q-1)
3. 选取小于r ,且与 r 互质的整数 e
4. 计算整数 d ,使得 ed≡1 mod r
5. 二元组 (N,e) 称为公钥,二元组 (N,d) 称为私钥
当需要加密消息 n 时(假设 n 是一个小于 N 整数,因为任何格式的消息都可转为整数表示),使用公钥 (N,e),按照
n^e≡c mod N 运算,可得到密文 c 。
对密文 c 解密时,用私钥 (N,d) ,按照c^d≡n mod N 运算,可得到原文 n 。
算法正确性证明省略。
由于用公钥加密的密文仅能用对应的私钥解密,而不能用公钥解密,因此称为非对称加密算法。通常情况下,公钥由消息的接收方公开,而私钥由消息的接收方自己持有。这样任何发送消息的人都可以用公钥对消息加密,而只有消息的接收方自己能够解密消息。
现在,你的任务是寻找一种可行的方法来破解这种加密算法,即根据公钥破解出私钥,并据此解密密文。
由于用公钥加密的密文仅能用对应的私钥解密,而不能用公钥解密,因此称为非对称加密算法。通常情况下,公钥由消息的接收方公开,而私钥由消息的接收方自己持有。这样任何发送消息的人都可以用公钥对消息加密,而只有消息的接收方自己能够解密消息。
现在,你的任务是寻找一种可行的方法来破解这种加密算法,即根据公钥破解出私钥,并据此解密密文。
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
//样例中 p = 11, q = 17
Solution
一开始被题意吓到了……
其实仔细捋一下,就按如下步骤就完了。
因为有$N$,所以可以$Pollard-Rho$求出来$p$和$q$。
求出来$p$和$q$,就可以求出来$r$。
求出来$r$,就可以$exgcd$解出来$d$.
求出来$d$,就可以用快速幂求出来$n$。
然后这题就没了……
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #define LL long long 6 using namespace std; 7 8 LL T,maxn,x; 9 LL prime[10]={2,3,5,7,11,13,17,19,23}; 10 11 LL Mul(LL a,LL b,LL MOD) 12 { 13 LL tmp=a*b-(LL)((long double)a*b/MOD+0.1)*MOD; 14 return tmp<0?tmp+MOD:tmp; 15 } 16 17 LL Qpow(LL a,LL b,LL MOD) 18 { 19 LL ans=1; 20 while (b) 21 { 22 if (b&1) ans=Mul(ans,a,MOD); 23 a=Mul(a,a,MOD); b>>=1; 24 } 25 return ans; 26 } 27 28 LL gcd(LL a,LL b) {return b==0?a:gcd(b,a%b);} 29 30 bool Miller_Rabin(LL n) 31 { 32 if (n==2) return 1; 33 if (n<2 || n%2==0) return 0; 34 LL m=n-1,l=0; 35 while (m%2==0) ++l, m>>=1; 36 for (int i=0; i<9; ++i) 37 { 38 LL p=prime[i],w=Qpow(p,m,n); 39 if (w==1 || w==n-1 || p==n) continue; 40 for (int j=1; j<=l; ++j) 41 { 42 LL u=Mul(w,w,n); 43 if (u==1 && w!=1 && w!=n-1) return 0; 44 w=u; 45 } 46 if (w!=1) return 0; 47 } 48 return 1; 49 } 50 51 LL Pollard_Rho(LL n,LL c) 52 { 53 LL x=rand()%n,y=x,p=1,k=2; 54 for (LL i=1; p==1; ++i) 55 { 56 x=(Mul(x,x,n)+c)%n; 57 p=x>y?x-y:y-x; 58 p=gcd(p,n); 59 if (i==k) y=x,k+=k; 60 } 61 return p; 62 } 63 64 void Solve(LL n) 65 { 66 if (n==1) return; 67 if (Miller_Rabin(n)) {maxn=max(maxn,n); return;} 68 LL t=n; 69 while (t==n) t=Pollard_Rho(n,rand()%(n-1)+1); 70 Solve(t); Solve(n/t); 71 } 72 73 int main() 74 { 75 scanf("%lld",&T); 76 while (T--) 77 { 78 scanf("%lld",&x); 79 maxn=0; 80 Solve(x); 81 if (maxn==x) puts("Prime"); 82 else printf("%lld\n",maxn); 83 } 84 }