多重集下的组合数

与多重集的排列数不同组合数即是不含有相同数交换的数.

并不是很难.

Devu and Flowers

题面翻译

Devu 有 nn 个花瓶,第 ii 个花瓶里有 fif_i 朵花。他现在要选择 ss 朵花。

你需要求出有多少种方案。两种方案不同当且仅当两种方案中至少有一个花瓶选择花的数量不同。

答案对 109+710^9+7 取模。

1n20,0fi1012,0s10141\le n\le 20,0\le f_i\le 10^{12},0\le s\le 10^{14}

题目描述

Devu wants to decorate his garden with flowers. He has purchased nn boxes, where the ii -th box contains fif_{i} flowers. All flowers in a single box are of the same color (hence they are indistinguishable). Also, no two boxes have flowers of the same color.

Now Devu wants to select exactly ss flowers from the boxes to decorate his garden. Devu would like to know, in how many different ways can he select the flowers from each box? Since this number may be very large, he asks you to find the number modulo (109+7)(10^{9}+7) .

Devu considers two ways different if there is at least one box from which different number of flowers are selected in these two ways.

输入格式

The first line of input contains two space-separated integers nn and ss ( 1<=n<=201<=n<=20 , 0<=s<=10140<=s<=10^{14} ).

The second line contains nn space-separated integers f1,f2,... fnf_{1},f_{2},...\ f_{n} ( 0<=fi<=10120<=f_{i}<=10^{12} ).

输出格式

Output a single integer — the number of ways in which Devu can select the flowers modulo (109+7)(10^{9}+7) .

样例 #1

样例输入 #1

2 3
1 3

样例输出 #1

2

样例 #2

样例输入 #2

2 4
2 2

样例输出 #2

1

样例 #3

样例输入 #3

3 5
1 3 2

样例输出 #3

3

提示

Sample 1. There are two ways of selecting 33 flowers: 1,2{1,2} and 0,3{0,3} .

Sample 2. There is only one way of selecting 44 flowers: 2,2{2,2} .

Sample 3. There are three ways of selecting 55 flowers: 1,2,2{1,2,2} , 0,3,2{0,3,2} , and 1,3,1{1,3,1} .

就像这题就是问的多重集的组合数.

先考虑一种特殊情况,当s<=fis<=f_i对于所有的ii都成立.

那么方案数就非常非常简单,你可以看成有n1n-1个分隔符,用来分隔一个长度为ss的区间,那么方案数就是C(s+n1,n1)C(s+n-1,n-1).

不考虑这种特殊情况考虑一下容斥,我们定义dpidp_i表示对于第i种至少取了fi+1f_i+1个商品,对于这个的方案数就是C(s+n1(fi+1),n1)C(s+n-1-(f_i+1),n-1),可以广义容斥一下.

这里数据很大,但是n很小显然组合数要暴力算.

然后就做完了...

code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=21;
const int M=(1<<20);
const int mod=1e9+7;
const double pi=acos(-1);

ll f[N];
int bit[M];

ll qp(ll a,ll b)
{
	ll res=1;
	while(b)
	{
		if(b&1)	res=res*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return res;
}

ll C(ll a,ll b)
{
	if(b>a)			return 0;
	if(a<0||b<0)	return 0;
	ll res=1,ans=1;
	for(int i=b;i>=1;i--)
	{
		res=res*(a%mod)%mod;
		a--;
		ans=ans*i%mod;
	}
	return res*qp(ans,mod-2)%mod;
}

void run()
{
	ll n,s;
	cin>>n>>s;
	for(int i=0;i<n;i++)
		cin>>f[i];
	ll ans=0,m=(1<<n);
	for(int i=1;i<m;i++)
		bit[i]=bit[i>>1]+(i&1);
	for(int i=0;i<m;i++)
	{
		ll fm=s+n-1;
		for(int j=0;j<n;j++)
		{
			if(i>>j&1)	fm-=(f[j]+1);
		}
		if(bit[i]&1)
		{
			ans-=C(fm,n-1);
		}
		else
		{
			ans+=C(fm,n-1);
		}
		ans%=mod;
	}
	cout<<(ans%mod+mod)%mod<<'\n';
}

int main()
{
	int T=1;
//	scanf("%d",&T);
	while(T--)	run();
	return 0;
}

全部评论

相关推荐

废铁汽车人:秋招真是牛鬼蛇神齐聚一堂
点赞 评论 收藏
分享
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务