其他分享
首页 > 其他分享> > BZOJ4522 [Cqoi2016]密钥破解

BZOJ4522 [Cqoi2016]密钥破解

作者:互联网

<body>

4522: [Cqoi2016]密钥破解

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 1039  Solved: 603
[Submit][Status][Discuss]

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 。算法正确性证明省略。

由于用公钥加密的密文仅能用对应的私钥解密,而不能用公钥解密,因此称为非对称加密算法。通常情况下,公钥由消息的接收方公开,而私钥由消息的接收方自己持有。这样任何发送消息的人都可以用公钥对消息加密,而只有消息的接收方自己能够解密消息。

现在,你的任务是寻找一种可行的方法来破解这种加密算法,即根据公钥破解出私钥,并据此解密密文。

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]

HOME Back

题解

CQOI破解密码专场。

虽然不知道为什么\(x^{k(p-1)(q-1)+1}\equiv 1\ (\bmod pq)\),但是分析题意我们只需要把\(p,q\)分解出来就行了。

所以用上Pollard-Rho大整数分解算法,以及Miller-Rabbin素性测试。然后其他的就是常规同余内用了。

最后说一下O(1)快速乘
O(1)快速乘

#include<bits/stdc++.h>
#define il inline
#define co const
template<class T>T read(){
    T data=0,w=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
    for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
    return data*w;
}
template<class T>il T read(T&x) {return x=read<T>();}
typedef long long LL;
using namespace std;

queue<LL> arr;
il LL mul(LL a,LL b,LL mod){
    LL ans=a*b-(LL)((long double)a/mod*b+1e-8)*mod;
    return ans<0?ans+mod:ans;
}
LL pow(LL a,LL b,LL mod){
    LL ans=1;
    for(;b;b>>=1,a=mul(a,a,mod))
        if(b&1) ans=mul(ans,a,mod);
    return ans;
}
LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;}
LL exgcd(LL a,LL b,LL&x,LL&y){
    if(!b) return x=1,y=0,a;
    LL z=exgcd(b,a%b,y,x);
    return y-=a/b*x,z;
}
LL Pollard_Rho(LL n,LL sed){
    LL i=1,k=2,x=rand()%(n-1)+1,y=x;
    while(true){
        x=(mul(x,x,n)+sed)%n;
        LL p=gcd(n,(y-x+n)%n);
        if(p!=1&&p!=n) return p;
        if(y==x) return n;
        if(++i==k) y=x,k<<=1;
    }
}
LL x[100];
bool Miller_Rabbin(LL n){
    if(n==2) return 1;
    LL s=20,t=0,u=n-1;
    while(!(u&1)) ++t,u>>=1;
    while(s--){
        LL a=rand()*rand()%(n-2)+2;
        x[0]=pow(a,u,n);
        for(int i=1;i<=t;++i){
            x[i]=mul(x[i-1],x[i-1],n);
            if(x[i]==1&&x[i-1]!=1&&x[i-1]!=n-1) return 0;
        }
        if(x[t]!=1) return 0; // Fermat
    }
    return 1;
}
void find(LL n,LL sed){
    if(n==1) return;
    if(Miller_Rabbin(n)) return arr.push(n);
    LL p=n,k=sed;
    while(p==n) p=Pollard_Rho(p,sed--);
    find(p,k),find(n/p,k);
}
LL p,q,e,d,N,c,r;
int main(){
    srand(19260817);
    read(e),read(N),read(c);
    find(N,107);
    p=arr.front(),arr.pop();
    q=arr.front(),arr.pop();
    exgcd(e,r=(p-1)*(q-1),d,*(new LL));
    d=(d%r+r)%r;
    printf("%lld %lld\n",d,pow(c,d,N));
    return 0;
}

标签:ch,return,LL,BZOJ4522,密钥,ans,私钥,Cqoi2016,mod
来源: https://www.cnblogs.com/autoint/p/11095279.html