Poj 2447 RSA

/**
*  url: http://poj.org/problem?id=2447
*  stratege: Pollard_Rho整数分解, 快速模取幂, 逆元求解, 扩展欧几里德
*  Author:Johnsondu (chennyDu)
*  Time: 2012-10-16 20:06 Around 
*  Status: 10921637	a312745658	2447	Accepted	156K	235MS	C++	2096B	2012-10-16 19:55:58
**/

/*
--------------------------------------------------
一开始一直TLE, 最后换了一个整数分解的模板,就过了。
--------------------------------------------------
*/

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std ;

#define LL __int64

LL 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 ;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值