BZOJ4802 欧拉函数 Millar_Rabin &&Pollard_Rho

233

题意就是求 N(N1e18) 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 ) ;
}

你可能感兴趣的:(BZOJ4802 欧拉函数 Millar_Rabin &&Pollard_Rho)