多重集下的组合数

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

并不是很难.

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;
}

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-11 12:31
以前小时候我最痛恨出轨、偷情的人,无论男女,为什么会出轨?现在我成了自己最讨厌的人,没想到分享的东西在牛客会被这么多人看,大家的评价都很中肯,我也认同,想过一一回复,但我还是收声了,我想我应该说说这件事,这件事一直压在我心里,是个很大的心结,上面说了人为什么出轨,我大概能明白了。我们大一下半年开始恋爱,开始恋爱,我给出了我铭记3年的承诺,我对她好一辈子,我永远不会背叛,我责任心太重,我觉得跟了我,我就要照顾她一辈子,我们在一起3年我都没有碰过她,她说往东我就往东,她说什么我做什么,她要我干什么,我就干什么!在学校很美好,中途也出过一些小插曲,比如男闺蜜、男闺蜜2号等等等。但我都强迫她改掉了,我...
牛客刘北:两个缺爱的人是没有办法好好在一起的,但世界上哪有什么是非对错?你后悔你们在一起了,但是刚刚在一起的美好也是真的呀,因为其他人的出现,你开始想要了最开始的自己,你的确对不起自己,21岁的你望高物远,你完全可以不谈恋爱,去过你想要的生活,你向往自由,在一起之后,你要想的不是一个人,而是两个人,你不是变心了,就像你说的,你受够了,你不想包容了,冷静几天是你最优的选择,爱人先爱己。
社会教会你的第一课
点赞 评论 收藏
分享
Lorn的意义:你这标个前端是想找全栈吗?而且项目确实没什么含金量,技术栈太少了,边沉淀边找吧 现在学院本想就业好一点四年至少得高三模式两年加油吧
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务