整数因子分解算法

奇葩的算法

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 m, last, sum, t, ret;
    int T;
    scanf("%d", &T);
    while( T-- && scanf( "%I64u",&m ) )
    {
        int flag = 0;
        if (m == 1) {
            printf("1 1\n");
            continue;    
        }
        cnt = last = sum = ret = t = 0;
        Pallord_Min( m );
        sort( num , num + cnt ,cmp);
        for (int i = 1; i < cnt; ++i) {
            if (num[i] != num[i-1])    {
                flag = 1;
                break;
            }
        }
        if (!flag) {
            printf("1 %I64u\n", m/num[0]);
            continue;
        }
        for (int i = 0; i < cnt; ++i) {
        //    printf("num[%d] = %I64u\n", i, num[i]);
            if (t == 0) {
                t = num[i];
                ret++;
                continue;        
            }
            if (num[i] == num[i-1]) {
                t *= num[i];
            //    printf("t = %I64u\n", t);
            }
            else {
                sum += t;
            //    printf("t = %I64u, sum = %I64u\n", t, sum);
                t = num[i];
                ++ret;
            }
        }
        printf("%I64u %I64u\n", ret, sum+t);
    }
    //system( "pause" );
    return 0;
}

posted on 2012-08-07 20:28  more think, more gains  阅读(419)  评论(0编辑  收藏  举报

导航