• 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;
    }
  • 相关阅读:
    改变DEV控件的字体 z
    软件加密的一些误区及防破解
    Devexpress GridControl中combobox级联显示 z
    Devexpress GridControl z
    陈发树云南白药股权败诉真相 取胜仅差三步 z
    重复的价值 周鸿祎
    lodop 控件实现web打印功能
    eclipse 启动报错 java was started but returned code=13
    Navicat 破解版的安装
    WIN10 64位 JDK的安装
  • 原文地址:https://www.cnblogs.com/ihopenot/p/5955992.html
Copyright © 2020-2023  润新知