zoukankan      html  css  js  c++  java
  • Bzoj4710--Jsoi2011分特产

    组合计数+容斥原理的题目

    考虑对于每一类特产分给所有人有多少种方式,就是把每类特产分给所有人的方案数乘积

    把x个物品分给n个人的方案数可以看成n-1个分隔符和x个物品的排列数,即为n-1+x个物品中选出x个物品的方案数,即C(x,x+n-1)

    但是这样会把不合法的状态也算入答案,所以可以容斥一波

    n个人中有a个人没分到东西的方案数即为把x个物品分给n-a个人的方案数,最后再乘上n个人中选a个人的方案数即可

    代码:

    #include<bits/stdc++.h>
    #define INF 1000000000
    #define LNF 100000000000000ll
    #define eps 1e-9
    #define LL long long
    #define MOD 1000000007
    inline int _max(int a,int b) {return a>b?a:b;}
    inline double _fabs(double a) {return a>0?a:-a;}
    
    using namespace std;
    #define MAXN 1005
    #define MAXM 30005
    
    LL C[MAXN*2][MAXN*2],ans;
    int n,m,a[MAXN],mx;
    
    void Get_C() {
        int r=n+mx-1;
        for(int i=0;i<=r;i++) C[i][0]=1;
        for(int i=0;i<=r;i++) C[0][i]=1;
        for(int i=1;i<=r;i++) for(int j=1;j<=r;j++) 
            C[i][j]=(C[i-1][j]+C[i][j-1])%MOD;
    }
    
    LL comp(int v) {
        LL ret=C[v][n-v];if(v&1) ret=-ret;
        for(int i=1;i<=m;i++) 
            ret=ret*C[a[i]][n-1-v]%MOD;
        return ret;
    }
    
    int main() {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++) scanf("%d",&a[i]),mx=_max(mx,a[i]);
        Get_C();
        for(int i=0;i<=n;i++) {
            ans=(ans+comp(i))%MOD;
            if(ans<0) ans+=MOD*(-ans/MOD+1);
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    NET导入Excel带进度条。
    直接拿来用,最火的.NET开源项目(beta)
    Darren Ji
    接口和抽象类有什么区别
    wpf博客
    jQuery动态改变图片显示大小(修改版)
    S32K的make过程
    TortoiseGit安装及使用
    Python:tkinter
    GCC学习笔记(二):编译选项
  • 原文地址:https://www.cnblogs.com/ihopenot/p/5955992.html
Copyright © 2011-2022 走看看