zoukankan      html  css  js  c++  java
  • 【CF451E】Devu and Flowers

    题目大意:求多重集合的组合数, (N le 1e14,M le 20)

    题解:
    考虑容斥原理,具体做法是枚举所有情况,即:枚举子集,第 i 位为 1 表示满足第 i 个条件,正负号采用 sign 进行判断。
    对于本题的组合数来说,上指标过大,导致没办法预处理阶乘和逆元进行快速回答,不过下指标很小,可以按照定义进行枚举计算。

    代码如下

    #include <bits/stdc++.h>
    using namespace std;
    const int mod=1e9+7;
    typedef long long LL;
    LL fpow(LL a,LL b,LL c){
    	LL ret=1%c;
    	for(;b;b>>=1,a=a*a%c)if(b&1)ret=ret*a%c;
    	return ret;
    }
    LL C(LL n,LL m){
    	if(n<m)return 0;
    	m=min(m,n-m);
    	LL ret=1,up=1,down=1;
    	for(int i=1;i<=m;i++){
    		up=up*(n-i+1)%mod;
    		down=down*i%mod;
    	}
    	down=fpow(down,mod-2,mod);
    	ret=ret*up%mod*down%mod;
    	return ret;
    }
    LL Lucas(LL n,LL m){
    	if(n<mod&&m<mod)return C(n,m);
    	return C(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod;
    }
    
    LL f[21],s,ans;
    int n;
    
    int main(){
    	scanf("%d%lld",&n,&s);
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&f[i]);
    	}
    	
    	for(int i=0;i<1<<n;i++){
    		LL tot=s,sign=1;
    		for(int j=1;j<=n;j++)
    			if(i>>(j-1)&1){
    				tot-=(f[j]+1);
    				sign=-sign;
    			}
    		if(tot<0)continue;
    		ans=(ans+Lucas(tot+n-1,n-1)*sign)%mod;
    	}
    	printf("%lld
    ",(ans+mod)%mod);
    	
    	return 0;
    } 
    
  • 相关阅读:
    第九周PSP
    c++的继承方式
    matlab的应用
    beta发布的评论
    本周psp
    历年作品点评
    JSON解析数据
    每周工作量及代码统计(第七周)
    词频统计(WEB)版
    评论alpha发布
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10979082.html
Copyright © 2011-2022 走看看