CSU1801(第十二届湖南省大学生计算机程序设计竞赛(热身赛)- D)

Problem : Mr. S’s Romance
Description :

给你 n 个数,把每个数都分解成素因子放进一个盒子中,要你从中至少抽一个数字相乘起来使得乘积是完全平方数。问有多少种方式。

Solution :

组合数公式+乘方快速幂+小优化。首先分解每个数。这里分解的时候要优化下,如果分解剩下来的数直接是一个素数,那么就把这个素因子的个数+1,然后直接跳出循环。然后就是组合,我们把盒子中的数按照素数分类,得到每个素数的个数,要想相乘起来的数字是完全平方数。那么每个素数取的个数就是偶数个。这样对于每个素数能取的方式总数就是 f(ai)=(0ai)+(2ai)+(4ai)+ 。而这个求和是有公式的: f(ai)=2ai1 。那么答案就是 ans=f(a0)f(a1)f(a2) 。但是题目中说了不能一个都不取,那么最终答案就是 ans=ans1

Code(C++) :

#include 
#include 

#include 

#define MAXN 1000005

using namespace std;

typedef long long LL;

bool isprime[MAXN];
int prime[MAXN];
int indexnum[MAXN];
int num;

const int TOP=80000;
const LL MOD=1000000000LL+7;

int get_prime()
{
    memset(isprime,true,sizeof(isprime));
    isprime[1]=false;
    for(int i=2;i*i4;i++)
        if(isprime[i])
            for(int j=2;i*j4;j++)
                isprime[i*j]=false;
    num=0;
    for(int i=1;i4;i++)
        if(isprime[i])
            indexnum[i]=num,prime[num++]=i;
    return num;
}

int a[TOP];

void deal(int x)
{
    for(int i=0;iif(isprime[x]){
            a[indexnum[x]]++;
            break;
        }
        while(x%prime[i]==0){
            a[i]++;
            x/=prime[i];
        }
        if(x==1)
            break;
    }
}

LL mul(LL x,LL n,LL mod)
{
    LL tmp=x;
    LL ans=1;
    while(n){
        if(n&1){
            ans*=tmp;
            ans%=mod;
        }
        tmp*=tmp;
        tmp%=mod;
        n>>=1;
    }
    return ans%mod;
}

int main()
{
    //freopen("in.data","r",stdin);
    get_prime();
    int T,K=1;
    for(cin>>T;T--;){
        int n;
        scanf("%d",&n);
        memset(a,0,sizeof(a));
        for(int i=0;iint tmp;
            scanf("%d",&tmp);
            deal(tmp);
        }
        LL ans=1;
        for(int i=0;iif(a[i])
                ans=ans*mul(2,a[i]-1,MOD)%MOD;
        ans=(ans-1+MOD)%MOD;
        printf("Case #%d:\n%lld\n",K++,ans);
    }
    return 0;
}

你可能感兴趣的:(OJ,ACM算法竞赛)