/** * 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 ; }