HDU 4390 Number Sequence(容斥原理)

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 

题目:给出n个数,b1,b2,b3……bn,构造n个数,a1,a2,……an(ai>1),使得a1*a2*a3……an=b1*b2……bn;

http://acm.hdu.edu.cn/showproblem.php?pid=4390 

首先是将所有 的b进行素因子分解,则a和b的因子是完全一致的。

剩下的便是将所有b的因子,分给a

我们考虑某个素因子pi,如果有ci个,便成了子问题将ci个相同的物品放入到n个不同的容器中,种数为多少

但是要求ai>1,也就是容器不能为空,这是个问题。

我们考虑的是什么的情况,然后减去假设有一个确定是空的情况,发现可以用容斥原理解决

我们假设f[i]表示有i个容器的结果,c(n,i)*f[i]

将m个物品放到到不同的n个容器中,结果为c(n+m-1,n-1)

#include<iostream>
#include<cstdio>
#include <queue>
#include<cstring>
#include<algorithm>
#include<vector>
#define pb(a) push_back(a)
#define MOD 1000000007
#define LL long long
using namespace std;
int n;
LL c[505][505];
vector<int>p;
void fuck(int num)
{
    for(int i=2;i*i<=num;i++)
    {
        while(num%i==0)
        {
            num/=i;
            p.pb(i);
        }
    }
    if(num>1) p.pb(num);
}
void Init()
{
    for(int i=0;i<=500;i++)
    {
        c[i][0]=c[i][i]=1;
        for(int j=1;j<i;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%MOD;
    }
}
LL get(int n,int m)
{
    return c[m+n-1][n-1];
}
LL slove()
{
    int a[1005]={1},cnt=0;
    sort(p.begin(),p.end());
    for(int i=1;i<p.size();i++)
    {
        if(p[i]!=p[i-1]) a[++cnt]=1;
        else a[cnt]++;
    }
    LL ans=1;
    for(int i=0;i<=cnt;i++)  ans=(ans*get(n,a[i]))%MOD;
    //cout<<ans<<endl;
    for(int i=1;i<n;i++)
    {
        LL tmp=c[n][i];
        for(int j=0;j<=cnt;j++)
        {
            tmp=(tmp*get(n-i,a[j]))%MOD;
        }
        if(i&1) ans=((ans-tmp)%MOD+MOD)%MOD;
        else ans=(ans+tmp)%MOD;
    }
    return ans;
}
int main()
{
    Init();
    while(scanf("%d",&n)!=EOF)
    {
        p.clear();
        for(int i=0;i<n;i++)
        {
            int k;
            scanf("%d",&k);
            fuck(k);
        }
        printf("%I64d\n",slove());
    }
    return 0;
}


你可能感兴趣的:(HDU 4390 Number Sequence(容斥原理))