HDU4344(大数分解)

题目:Mark the Rope

 

题意就是给一个数,然后求这个数的所有因子中组成的最大的一个子集,其中1和本身除外,使得在这个子集中元素两两互素,求最大子集的元素个

数,并且求出和最大的值。

找规律就不难发现其实答案就是先大数分解n,例如,180=2^2*3^2*5,那么就输出3   18   ,这两个数分别是素因子的个数和2^2,3^2,5的和。

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <algorithm>

#include <iostream>



const int Times=10;

const int N=550;



using namespace std;

typedef unsigned __int64 LL;



LL ct,cnt;

LL fac[N],num[N];



LL gcd(LL a,LL b)

{

    return b? gcd(b,a%b):a;

}



LL multi(LL a,LL b,LL m)

{

     LL ans=0;

     while(b)

     {

         if(b&1)

         {

             ans=(ans+a)%m;

             b--;

         }

         b>>=1;

         a=(a+a)%m;

     }

     return ans;

}



LL quick_mod(LL a,LL b,LL m)

{

     LL ans=1;

     a%=m;

     while(b)

     {

         if(b&1)

         {

             ans=multi(ans,a,m);

             b--;

         }

         b>>=1;

         a=multi(a,a,m);

     }

     return ans;

}



bool Miller_Rabin(LL n)

{

    if(n==2) return true;

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

    LL a,m=n-1,x,y;

    int k=0;

    while((m&1)==0)

    {

        k++;

        m>>=1;

    }

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

    {

        a=rand()%(n-1)+1;

        x=quick_mod(a,m,n);

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

        {

            y=multi(x,x,n);

            if(y==1&&x!=1&&x!=n-1) return false;

            x=y;

        }

        if(y!=1) return false;

    }

    return true;

}



LL Pollard_rho(LL n,LL c)

{

     LL x,y,d,i=1,k=2;

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

     while(true)

     {

         i++;

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

         d=gcd((y-x+n)%n,n);

         if(1<d&&d<n) return d;

         if(y==x) return n;

         if(i==k)

         {

             y=x;

             k<<=1;

         }

     }

}



void find(LL n,int c)

{

     if(n==1) return;

     if(Miller_Rabin(n))

     {

         fac[ct++]=n;

         return ;

     }

     LL p=n;

     LL k=c;

     while(p>=n) p=Pollard_rho(p,c--);

     find(p,k);

     find(n/p,k);

}



int main()

{

    int t;

    LL n,ans;

    scanf("%d",&t);

    while(t--)

    {

         scanf("%I64u",&n);

         ct=0;

         find(n,120);

         sort(fac,fac+ct);

         num[0]=1;

         int k=1;

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

         {

             if(fac[i]==fac[i-1])

                 ++num[k-1];

             else

             {

                 num[k]=1;

                 fac[k++]=fac[i];

             }

         }

         cnt=k;

         LL ret=0;

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

         {

             LL temp=1;

             for(int j=0;j<num[i];j++)

                 temp*=fac[i];

             ret+=temp;

         }

         if(cnt==1) ret/=fac[0];

         printf("%I64u %I64u\n",cnt,ret);

    }

    return 0;

}


 

 

你可能感兴趣的:(HDU)