poj 2429 GCD & LCM Inverse

一个对Miller_rabin与pallord的一个运用;

View Code
#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<algorithm>

#include<cmath>

#include<queue>

#include<set>

#include<map>

#include<cstring>

#include<vector>

#define LL unsigned long long

using namespace std;

LL p[10] = { 2,3,5,7,11,13,17,19,23,29 },num[100],ans,sq;

int cnt;

LL Multi( LL a, LL b ,LL n )

{

   LL sum = 0;

   while( b )

   {

       if( (b&1) ) sum = (sum + a)%n;

       a <<= 1;

       b >>= 1;

       if( a >= n ) a %= n;        

   }    

   return sum;

}

LL Quick_mod( LL a, LL b ,LL n )

{

   LL sum = 1;

   while( b )

   {

        if( ( b & 1 ) ) sum = Multi( sum , a , n );

        a = Multi( a , a ,n );

        b >>= 1;        

   }    

   return sum;

}

LL Miller_rabin( LL n )

{

    LL m = n - 1,d,L;

    int k=0;

    if( n == 2 ) return true;

    if( n < 2 || !(n & 1) ) return false;    

    while( !( m & 1 ) )

    {

       k ++  ; m >>= 1;

    }

    for( int i = 0; i < 10; i++ )

    {

         if( p[i] >= n ) return true;

         d = Quick_mod( p[i] , m ,n );

         if( d ==1 ) continue;

         for( int j = 0; j < k ; j++ )

         {

             L = Multi( d , d , n );

             if( L == 1 && d != 1 && d != (n-1) )

                 return false;

             d = L;        

         }    

         if( d != 1 ) return false;

    }

    return true;

}

LL Gcd( LL a ,LL b )

{

   return b == 0? a : Gcd( b , a%b );    

}

LL Pallord( LL n )

{

   LL x,y,c=0;

   LL i = 1,k=2,d;

   x = y = abs( rand() )%(n-1) + 1;

   while( c == 0 || c== 2 ) c = abs( rand() )%(n-1) + 1;

   do

   {

        i++;

        d = Gcd( y + n -x ,n );

        if( d > 1 && d < n )

            return d;

        if( i == k )

        {

           y = x;

           k <<= 1;    

        } 

        x = (Multi( x ,x ,n ) + c)%n;

   }while( x != y );

   return n;     

}

void Pallord_Min( LL n )

{

    if( n == 1 ) return ;

    if( Miller_rabin( n ) )

    {

       num[cnt++] = n;

       return ;    

    }    

    LL p = Pallord( n );

    Pallord_Min( p );

    Pallord_Min( n/p );

}

void Solve( int n ,LL val )

{

    if( n >= cnt )

    {

        if( val > ans && val <= sq )

            ans = val;

        return ;    

    }

    Solve( n + 1, val*num[n] );

    Solve( n + 1 , val );

}

bool cmp( LL a ,LL b )

{

    return a < b;    

}

int main(  )

{

    LL n,m;

    while( scanf( "%I64u %I64u",&n,&m )==2 )

    {

        if( n > m ) swap( n , m );

        cnt = 0;

        m /= n;

        Pallord_Min( m );

        sort( num , num + cnt ,cmp);

        int j = 0;

        for ( int i = 1; i < cnt; i++ )  

        {  

        while ( num[i-1] == num[i] && i < cnt )  

            num[j] *= num[i++];  

        if ( i < cnt ) num[++j] = num[i];  

        }  

        ans = 1;

        sq = (LL)sqrt(m*1.0);

        cnt = j + 1;

        Solve( 0 ,1 );    

        printf( "%I64u %I64u\n",ans*n,(m/ans) * n );

    }

    //system( "pause" );

    return 0;

}

你可能感兴趣的:(inverse)