1 条题解

  • 1
    @ 2026-3-1 0:15:21

    每个人至少要分到一个礼物不好求,那么可以求"有ii个人没有分到礼物" 相当于多了ni1n-i-1个礼物,人少了ii个,因此此时的组合数为Ca[j]+ni1ni1C_{a[j]+n-i-1}^{n-i-1} 然后容斥原理应用:首先选ii个空手的人,有CniC_n^i种选择方式; 每一项* C(n, i):选择哪ii个人空手。

    容斥的符号规则:当ii为偶数时(空手人数为偶),方案数加;当ii为奇数时(空手人数为奇),方案数减; 代码如下:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long LL;
    
    const int N = 1e5 + 10;
    const LL mod = 1e9 + 7;
    
    LL n, m;
    LL a[N];
    LL fact[N], infact[N];
    LL dp[N];
    
    LL qmi(LL a, LL b, LL m){
    	LL res = 1;
    	while(b){
    		if(b & 1) res = (LL) res * a % m;
    		a = (LL) a * a % m;
    		b >>= 1;
    	}
    	return res;
    }
    
    void init(){
    	fact[0] = 1;
    	infact[0] = 1;
    	for(LL i = 1; i < N; i ++) {
            fact[i] = (LL)fact[i - 1] * i % mod;
            infact[i] = qmi(fact[i], mod - 2, mod) % mod;
        }  
    }
    
    LL C(LL a, LL b)
    {
        if(a < b) return 0;
        return fact[a] * infact[b] % mod * infact[a - b] % mod;
    }
    
    int main(){
    	init();
    	cin >> n >> m;
    	for(int i = 1; i <= m; i++){
    		cin >> a[i];
    	}
    	
    	for(int i = 0; i < n; i++){	//枚举空的人数 
    		dp[i] = 1;
    		for(LL j = 1; j <= m; j++){	//种类 
    			dp[i] = (LL)(dp[i] % mod) * (LL)C(a[j] + n - i - 1, n - i - 1) % mod;
    		}
    	}
    	
    	//容斥
    	LL res = 0;
    	for(LL i = 0; i < n; i++){
    		LL temp = dp[i] * C(n, i) % mod; 
    		if(i % 2 != 0) res -= (LL)(temp % mod + mod) % mod;
    		else res += (LL)(temp % mod) % mod;
    	} 
    	cout << (res % mod + mod) % mod << endl;
    	return 0;
    }
    
    //146 150 72
    

    信息

    ID
    263
    时间
    1000ms
    内存
    256MiB
    难度
    7
    标签
    (无)
    递交数
    24
    已通过
    7
    上传者