Poj 2447 RSA

来源:互联网 发布:java reflectasm 编辑:程序博客网 时间:2024/06/07 03:36
/***  url: http://poj.org/problem?id=2447*  stratege: Pollard_Rho整数分解, 快速模取幂, 逆元求解, 扩展欧几里德*  Author:Johnsondu (chennyDu)*  Time: 2012-10-16 20:06 Around *  Status: 10921637a3127456582447Accepted156K235MSC++2096B2012-10-16 19:55:58**//*--------------------------------------------------一开始一直TLE, 最后换了一个整数分解的模板,就过了。--------------------------------------------------*/#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <cstring>using namespace std ;#define LL __int64LL C, E, N, P, Q, T, M, D ;LL gcd (LL a, LL b){    return b ? gcd (b, a%b) : a ;}LL Mulit_mod(LL a,LL b,LL n)    //此处即为把乘法转换为加法{    LL ret = 0,temp = a%n;    while (b)    {        if (b&1) ret = ret + temp;        if (ret > n) ret -= n;        temp <<= 1;        if (temp > n) temp -= n;        b >>= 1;    }    return ret;}long int random(){    LL a;    a = rand();    a *= rand();    a *= rand();    a *= rand();    return a;}LL Abs (LL x){return x < 0 ? -x : x ;}LL Pollard_Rho(LL n) {      if(!(n&1)) return 2;      while(true)      {          LL x=Abs((LL)rand())%n,y=x;          LL c=Abs((LL)rand())%n;          if(c==0||c==2) c=1;          for(int i=1,k=2;;i++)          {              x = Mulit_mod(x,x,n);              if (x >= c) x -= c; else x += n - c ;              if (x == n) x = 0 ;              if (x == 0) x = n-1; else x --;              LL d = gcd (x>y ? x-y: y-x, n);              if (d == n) break ;              if (d != 1) return d ;              if (i == k) { y = x; k <<= 1 ; }          }      }  }  void exgcd (LL a, LL b, LL &d, LL &x, LL &y){    if (b == 0)    {        d = a ;        x = 1 ;        y = 0 ;        return ;    }    exgcd (b, a%b, d, x, y) ;    LL tmp = x ;    x = y ;    y = tmp - a/b * y ;}LL pow_mod (LL a, LL b, LL Mod){    LL ret = 1 ;    while (b)    {        if (b & 1)            ret = Mulit_mod (ret, a, Mod) ;  //Multi_mod 把乘法转换为加法,避免超过数据范围        a = Mulit_mod (a, a, Mod) ;        b >>= 1 ;    }    return ret ;}int main (){    LL x, y, d ;    while (scanf ("%I64d%I64d%I64d", &C, &E, &N) != EOF)    {        P = Pollard_Rho (N) ;// 告诉N,通过分解N(已知N为2个素数的乘积)        Q = N / P ;// 得到P, Q        T = (P-1)*(Q-1) ;           // 依题意,得到Q        exgcd (E, T, d, x, y) ;     // 求逆元(E * D) mod T = 1         D = (x%T + T) % T ;         // 此为D的值        M = pow_mod (C, D, N) ;     // M = (C ^ D) mod N  快速模取幂,注意数据范围故看前面注释        printf ("%I64d\n", M) ;     // 输出    }    return 0 ;}

原创粉丝点击