题目大意
- 选取两个不同的质数 p , q
- 令 N=p×q,r=(p−1)(q−1)
- 选取一个小于
r
的整数
e ,且 e 与r 互质 - 计算整数
d
满足
e⋅d ≡ 1 ( % r )
有以下两则性质:
1.
ne ≡ c ( % N )
2.
cd ≡ n ( % N )
现在已知
e , N , c
求
n , d
Data Constraint
对于
30%
的测试数据,
N≤106
对于
50%
的测试数据,
N≤1014
对于
100%
的测试数据,
N≤262
题解
对于 30% 的数据,直接暴力做一下。
对于
50%
的数据,对于有一点数论基础的同学,可以轻易发现
d
就是
对于
对于
100%
的数据,可以发现
50%
的算法真正的复杂度其实都是枚举求
p,q
。如果我们能快速得出
p,q
,那么问题就解决了。
这里引入一个算法——
Pollard Rho
具体细节,这里不再赘述,详见Pollard_rho.pdf
简述一下它的思想:
假如我们随机一个数,那么它是
N
的因子的概率为
其他的细节诸如生成随机数,和判环详见pdf。
温馨提醒:本体做乘法的时候会爆long long,可以用加法代替乘法。
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<ctime>
using namespace std ;
typedef long long ll ;
typedef unsigned long long ull ;
ll e , N , c , D ;
ll p , q , r , d ;
void Exgcd( ll a , ll b , ll &x , ll &y ) {
if ( b == 0 ) {
x = 1 ;
y = 0 ;
return ;
}
Exgcd( b , a % b , x , y ) ;
ll t = x ;
x = y ;
y = t - (a / b) * y ;
}
ll Calc() {
ll x , y ;
Exgcd( e , r , x , y ) ;
return (x + r) % r ;
}
ll mul( ll x , ll y ) {
if ( y == 1 ) return x ;
return (2ll * mul( x , y / 2 ) % N + ( y % 2 ? x : 0 )) % N ;
}
ll Power( ll x , ll k ) {
ll s = 1 ;
while ( k ) {
if ( k % 2 == 1 ) s = mul( s , x ) % N ;
x = mul( x , x ) % N ;
k /= 2 ;
}
return s ;
}
ll js( ll x ) { return x < 0 ? -x : x ; }
ll f( ll x ) { return (mul( x , x ) + D) % N ; }
ll gcd( ll x , ll y ) { return y == 0 ? x : gcd( y , x % y ) ; }
int main() {
freopen( "crack.in" , "r" , stdin ) ;
freopen( "crack.out" , "w" , stdout ) ;
srand( time(0) ) ;
cin >> e >> N >> c ;
D = rand() % N ;
while ( 1 ) {
ll a , b ;
a = b = rand() % N + 1 ;
while ( 1 ) {
a = f(a) ;
b = f(f(b)) ;
if ( a == b ) break ;
int d = gcd( js( a - b ) , N ) ;
if ( d == 1 || d == N ) continue ;
if ( d > 1 ) { p = d ; break ; }
}
if ( p ) break ;
D -- ;
}
q = N / p ;
r = N + 1 - (p + q) ;
d = Calc() ;
cout << d << " " << Power( c , d ) << endl ;
return 0 ;
}
以上.