BZOJ 4522: [Cqoi2016]密钥破解

http://www.lydsy.com/JudgeOnline/problem.php?id=4522

题目:给你RSA密钥的公钥和密文,求私钥和原文,其中\(N=pq\le 2^{62}\),p和q为质数。

RSA加密算法:https://en.wikipedia.org/wiki/RSA_(cryptosystem)

N的范围较小,我们可以用pollard-rho算法在期望O(N^0.25)的时间把N分解出来,用exgcd求逆元之后直接代入。

因为懒,写了一个很短的模板。速度还行,进了第一页。

upd:更新了模板,在另一篇文章里面。

/**************************************************************
    Problem: 4522
    User: will7101
    Language: C++
    Result: Accepted
    Time:392 ms
    Memory:1292 kb
****************************************************************/
 
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int MAXN = 100005;
ll mmul(ll a, ll b, ll m){ll r=0;for(;b;b>>=1,a=a+a>=m?a+a-m:a+a)if(b&1)r=r+a=>m?r+a-m:r+a;return r;}
ll mpow(ll a, ll b, ll m){ll r=1;for(;b;b>>=1,a=mmul(a,a,m))if(b&1)r=mmul(r,a,m);return r;}
ll gcd(ll a, ll b){return a?gcd(b%a,a):b;}
ll exgcd(ll a, ll b, ll &x, ll &y){
    if(a==0) return x=0, y=1, b;
    ll t=exgcd(b%a, a, y, x);
    x-=y*(b/a); return t;
}
ll work(ll n, ll c)
{
    ll x, y;
    x=y=rand();
    while(1){
        x=(mmul(x,x,n)+c)%n;
        y=(mmul(y,y,n)+c)%n;
        y=(mmul(y,y,n)+c)%n;
        if(x==y) return 1;
        ll p=gcd(x>y?x-y:y-x, n);
        if(p>1) return p;
    }
}
int main()
{
    srand(19260817);
    ll e, n, C, p, q, c, r, x, y;
    cin>>e>>n>>C;
    c=1;
    while((p=work(n, c))==1) c++;
    q=n/p; r=(p-1)*(q-1);
    exgcd(e, r, x, y); x=(x+r)%r;
    cout<<x<<' '<<mpow(C,x,n);
    return 0;
}
posted @ 2017-03-12 15:40  will7101  阅读(426)  评论(0编辑  收藏  举报