解题思路
我们只要求出(p)和(q),问题就迎刃而解了。那么就需要Pollard_Rho算法求(p)和(q)。值得注意的是,由于(n)不是素数,所以求逆元的时候需要用(exgcd)而不是费马小定理。
参考程序
#include <bits/stdc++.h>
#define LL long long
using namespace std;
LL SlowMultiply( LL x, LL y, LL Mod ) {
LL Ans = 0ll;
for( ; y; y >>= 1, x = ( x + x ) % Mod )
if( y & 1 )
Ans = ( Ans + x ) % Mod;
return Ans;
}
LL FastPow( LL x, LL y, LL Mod ) {
LL Ans = 1ll;
for( ; y; y >>= 1, x = SlowMultiply( x, x, Mod ) )
if( y & 1 )
Ans = SlowMultiply( Ans, x, Mod );
return Ans;
}
LL gcd( LL x, LL y ) {
LL m = x % y;
while( m ) {
x = y; y = m; m = x % y;
}
return y;
}
LL Pollard_Rho( LL N, LL Seed ) {
LL x, y;
x = y = rand() % N;
y = ( SlowMultiply( y, y, N ) + Seed ) % N;
while( x != y ) {
LL d = gcd( ( x - y > 0 ) ? x - y : y - x, N );
if( d > 1 ) return d;
x = ( SlowMultiply( x, x, N ) + Seed ) % N;
y = ( SlowMultiply( y, y, N ) + Seed ) % N;
y = ( SlowMultiply( y, y, N ) + Seed ) % N;
}
return N;
}
void Exgcd( LL a, LL b, LL &x, LL &y ) {
if( b == 0 ) {
x = 1ll, y = 0ll;
return;
}
Exgcd( b, a % b, y, x );
y -= a / b * x;
return;
}
LL Inv( LL a, LL b ) {
LL x, y;
Exgcd( a, b, x, y );
if( x < 0 ) x += b;
return x;
}
int main() {
LL e, N, c;
scanf( "%lld%lld%lld", &e, &N, &c );
LL p = N, q = 1;
for( LL Seed = 19260817; p == N; p = Pollard_Rho( N, Seed-- ) );
q = N / p;
LL r = ( p - 1 ) * ( q - 1 );
LL d = Inv( e, r );
printf( "%lld %lld
", d, FastPow( c, d, N ) );
return 0;
}