HDU4390 Number Sequence 【容斥原理+组合数学】

传送门

Given a number sequence b 1,b 2…b n.
Please count how many number sequences a 1 , a 2 , . . . , a n satisfy the condition that a 1 a 2 . . . a n = b 1 b 2 b n ( a i > 1 ) .
题意:对于等式 a 1 a 2 . . . a n = b 1 b 2 b n ( a i > 1 ) .,已知b数组,求有多少种可能的a数组,a数组中每个数都大于1。
分析:题目可以转化成把一个整数拆分成n个整数相乘,这个整数可以分解成m个质因子,每个因子出现次数为 x i ,如果 a i 可以为1,则直接可以转化为一种放球问题,把x个相同的球放到n个盒子里。有 m 种球。答案就为 i = 1 m C n + x i 1 n 1 但是题目要求 a i > 1 所以要用容斥定理排除不符合要求的方案。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MOD=1e9+7;
LL c[201][201];
int a[5000],pri[2000],num[2000];
int main()
{
    c[0][0]=1;
    for(int i=1;i<=200;i++)
    {
        for(int j=0;j<=i;j++)
        {
            if(j==0||j==i)c[i][j]=1;
            else
            c[i][j]=(c[i-1][j]+c[i-1][j-1])%MOD;
        }
    }
    int n,m,x,nu;
    while(scanf("%d",&n)!=EOF)
    {
        m=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            for(int j=2;j*j<=x;j++)
            {
                while(x%j==0)
                {
                    a[++m]=j;
                    x/=j;
                }
            }
            if(x!=1)a[++m]=x;
        }
        sort(a+1,a+m+1);
        pri[1]=a[1];
        num[1]=1;
        nu=1;
        for(int i=2;i<=m;i++)
        {
            if(a[i]==a[i-1])
            num[nu]++;
            else
            {
                nu++;
                pri[nu]=a[i];
                num[nu]=1;
            }
        }
        LL ans=0;
        for(int i=0;i<n;i++)
        {
            LL tem=c[n][i];
            for(int j=1;j<=nu;j++)
            {
                tem=tem*c[num[j]+n-1-i][n-1-i]%MOD;
            }
            if(i&1)
                ans=(ans-tem)%MOD;
            else
                ans=(ans+tem)%MOD;
        }
        ans=(ans%MOD+MOD)%MOD;
        printf("%lld\n",ans);
    }
}

猜你喜欢

转载自blog.csdn.net/m0_37953323/article/details/81062410
今日推荐