[CQOI2016]密钥破解

难啊!

一.题目

传送门

二.题解

这道题不知道大家有没有看出来,其实是一道数论板题,Pollard rho算法板题。
其实特别难看出来,但只要我们一分析就什么都水落石出了。
分析
N = p q N = p * q\quad①
r = ( p 1 ) ( q 1 ) r = (p - 1) * (q - 1)\quad②
g c d ( r , e ) = 1 gcd(r,e) = 1\quad③
e d 1 ( m o d r ) e * d \equiv 1(mod\quad r)\quad④
n e 1 ( m o d N ) n^{e}\equiv 1(mod\quad N)\quad⑤
c d n ( m o d N ) c^{d}\equiv n(mod\quad N)\quad⑥
已知: N , e , c N,e,c

  • 这样一分析也就一目了然:
    先用Pollard rho分解出p和q
    然后用扩展欧几里得求出d
    最后再求出n即可
  • 再说一下如何用欧几里得:
    可以看到,④式可以变式为:
    e d + r x = 1 ( x ) e*d + r * x = 1 (x求出来之后没有用,只是当一个参数)

最后上代码:

三.Code

#pragma GCC optimize(2)
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <ctime>
using namespace std;
#define LL long long

LL p, q, T, e, N, c, d, n, r;

inline LL qkcheng (LL x, LL y, LL mod){
    LL sum = 0;
    x %= mod;
    while (y){
        if (y & 1)
            sum = (sum + x) % mod;
        x = (x << 1) % mod;
        y >>= 1;
    }
    return sum;
}
inline LL qkpow (LL x, LL y, LL mod){
    x %= mod;
    LL sum = 1;
    while (y){
        if (y & 1)
            sum = qkcheng (sum, x, mod);
        x = qkcheng (x, x, mod);
        y >>= 1;
    }
    return sum;
}
inline bool miller_rabin (LL n){
    if (n == 2 || n == 3 || n == 5 || n == 7)
        return 1;
    if (!(n % 2) || !(n % 3) || !(n % 5) || !(n % 7))
        return 0;
    LL m = n - 1, k = 0;
    while (!(m & 1)){
        k ++;
        m >>= 1;
    }
    for (register LL i = 1; i <= 1; i ++){
        LL a = rand () % (n - 1) + 1, x = qkpow (a, m, n), y;
        for (register LL j = 1; j <= k; j ++){
            y = qkcheng (x, x, n);
            if (y == 1 && x != 1 && x != n - 1)
                return 0;
            x = y;
        }
        if (y != 1)
            return 0;
    }
    return 1;
}
inline LL gcd (LL x, LL y){
    if (! y)
        return x;
    return gcd (y, x % y);
}
inline LL pollard_rho (LL n, LL c){
    LL x = rand () % n, y = x, k = 2, i = 1;//全军出鸡,针对rand,你们的含精量呀?
    while (1){
        i ++;
        x = (qkcheng (x, x, n) + c) % n;
        LL d = gcd (fabs (x - y), n);
        if (d > 1 && d < n)
            return d;
        if (x == y)
            return n;
        if (i == k){
            y = x;
            k <<= 1;
        }
    }
}
inline void Find (LL n){
    if (miller_rabin (n)){
        p = n;
        return ;
    }
    LL tmp = n;
    while (tmp >= n)
        tmp = pollard_rho (tmp, rand () % (n - 1) + 1);
    Find (tmp);
    if (p)
        return ;
    Find (n / tmp);
}
inline LL exgcd (LL a, LL b, LL &x, LL &y){
    if (! b){
        x = 1, y = 0;
        return a;
    }
    LL tmp = exgcd (b, a % b, y, x);
    y = ((y - qkcheng(x, a / b, r) % r) % r + r) % r;
    return tmp;
}
int main (){
    srand (20060123);//注意,一定要写!!!
    scanf ("%lld %lld %lld", &e, &N, &c);
    Find (N);
    q = N / p;
    r = qkcheng ((p - 1), (q - 1), N);
    LL x;
    exgcd (e, r, d, x);
    n = qkpow (c, d, N);
    printf ("%lld %lld\n", d, n);
    return 0;
}

谢谢!

发布了61 篇原创文章 · 获赞 32 · 访问量 8337

猜你喜欢

转载自blog.csdn.net/weixin_43908980/article/details/101527583