题意就是求 N(N≤1e18) N ( N ≤ 1 e 18 ) 的欧拉函数值。
不知道为什么自己的随机函数不加一个数会GG
就用积性函数算呀…分解质因数就好了…
# include
inline unsigned int Rand ( ) {
static unsigned int seed ( 233 ) ;
seed = ( seed * 16807 + 151 ) ;
return seed ;
}
template < class T >
inline T mul ( T a, T b, const T& P ) {
a %= P, b %= P ;
T rt ( 0 ) ;
for ( ; b ; b >>= 1, a = ( a + a >= P ? a + a - P : a + a ) )
if ( b & 1 ) {
if ( ( rt += a ) >= P ) rt -= P ;
}
return rt ;
}
template < class T >
inline T mpow ( T a, T x, const T& P ) {
register T rt ( 1 ) ;
for ( ; x ; x >>= 1, a = mul ( a, a, P ) )
if ( x & 1 ) {
rt = mul ( rt, a, P ) ;
}
return rt ;
}
template < class T > inline T Abs ( T a ) { return a > 0 ? a : -a ; }
template < class T > inline T gcd ( T a, T b ) { while ( a ^= b ^= a ^= b %= a ) ; assert ( b ) ; return b ; }
namespace Millar_Rabin {
const int PN = 13 ;
const int primes [] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41 } ;
inline bool witness ( long long prime, long long idx, int times, long long n ) {
long long p = mpow ( prime, idx, n ) ;
if ( p == n - 1 || p == 1 ) return 0 ;
while ( times -- ) {
p = mul ( p, p, n ) ;
if ( p == n - 1 || p == 1 ) return 0 ;
}
return 1 ;
}
inline bool main ( long long n ) {
for ( int i = 0 ; i < PN ; ++ i ) {
if ( n == primes [i] ) return 1 ;
if ( n % primes [i] == 0 ) return 0 ;
}
long long p = n - 1 ;
int times = 0 ;
while ( ( p & 1 ) == 0 ) {
++ times ;
p >>= 1 ;
}
for ( int i = 0 ; i < PN ; ++ i )
if ( witness ( primes [i], p, times, n ) ) return 0 ;
return 1 ;
}
}
namespace Pollard_Rho {
int cnt ( 0 ) ;
long long factor [110] ;
void PR ( long long n ) {
if ( Millar_Rabin :: main ( n ) ) {
factor [cnt ++] = n ;
return ;
}
long long a, b, c, d ;
for ( ; ; ) {
c = Rand ( ) % n ;
a = b = Rand ( ) % n ;
b = ( mul ( b, b, n ) + c ) % n ;
while ( a ^ b ) {
d = gcd ( Abs ( b - a ), n ) ;
if ( d != 1 && d < n ) {
PR ( d ), PR ( n / d ) ;
return ;
}
a = ( mul ( a, a, n ) + c ) % n ;
b = ( mul ( b, b, n ) + c ) % n ;
b = ( mul ( b, b, n ) + c ) % n ;
}
}
}
}
int main ( ) {
long long n ;
std :: cin >> n ;
if ( n == 1 ) return !printf ( "1\n" ) ;
using namespace Pollard_Rho ;
PR ( n ) ;
std :: sort ( factor, factor + cnt ) ;
long long rt = factor [0] - 1 ;
for ( int i = 1 ; i < cnt ; ++ i ) {
if ( factor [i] == factor [i - 1] ) rt *= factor [i] ;
else rt *= factor [i] - 1 ;
}
return ! printf ( "%lld\n", rt ) ;
}