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
",cnt,ret);
    }
    return 0;
}


 

原文地址:https://www.cnblogs.com/dyllove98/p/3157383.html