「CF451E Devu and Flowers」题解

Description

CF451E Devu and Flowers


有限制多重集组合模板题。
可转化题目

\(n\) 种盒子,每个盒子可以放的小球数最多为 \(f_i\),盒子可为空,求总共放 \(s\) 个球的方案数,答案对 1e9+7 取模。

发现直接求方案不好做,但是总方案和不合法的方案都容易算出,考虑容斥。
总方案十分经典,可以考虑成 \(s\) 个小球,\(n-1\) 块隔板,隔板可相邻(某个盒子为空),问隔开的方案。
那么因为隔板可以相邻,直接把小球和隔板当作空考虑,选出 \(n-1\) 个空的方案,即 \(\binom{s+n-1}{n-1}\)

到这一步可以看出组合数的下项非常大但上项极小,使用一个常用的技巧,即把上下项约掉一部分后再分开运算。

\[\binom{s+n-1}{n-1}=\frac{(s+n-1)!}{s!(n-1)!}=\frac{(s+n-1)!}{s!}\times\frac{1}{(n-1)!} \]

前一项只用运算 \(n-1\) 次,后一项用逆元预处理可 \(\Theta(1)\) 求得,所以单次求组合数时间复杂度为 \(\Theta(n)\)
解决了组合数的问题,接下来就是很 naive 的容斥了,设 \(\operatorname{G[i]}\) 表示第 \(i\) 个盒子不合法的方案,\(S\) 表示总方案,则

\[Ans=S-\sum_{i=1}^nG[i]+\sum_{i=1}^n\sum_{j=i+1}^nG[i]G[j]-\sum_{i=1}^n\sum_{j=i+1}^n\sum_{k=j+1}^nG[i]G[j]G[k]...+(-1)^n\sum_{i=1}^n\sum_{j=i+1}^n\sum_{k=j+1}^n...\sum_{m=n}^nG[i]G[j]G[k]...G[m] \]

在枚举每个盒子不合法情况时显然不能直接球的个数,但是我们知道 \(f_i+1\) 个球的时候一定已经不合法。
那么我们直接把这些球放进第 \(i\) 个盒子,剩下的球继续分的都是不合法的方案。

\[G[i]=\binom{s-f_i+n-1}{n+1} \]

多个盒子时同理。
Code:

#include<cstdio>//直接转化为球相同+隔板,且隔板的数量极少 
#include<iostream>//枚举不合法时先控制成至少,因为剩下的隔板可以继续分配,然后相当于球减少了(f_i+1)个继续用求全集公式 
using namespace std;//然后就变成了一个小技巧,当下项极大时拆分一下即可 
const int Mod=1e9+7;
const int MAXN=25;
const int M=20;
#define ll long long
int n,o[2];
ll f[MAXN],s,fra[MAXN],ofra[MAXN],Ans;
ll ksm(ll a,int b)
{
	ll ans=1;
	while(b){
		if(b&1) ans=ans*a%Mod;
		a=a*a%Mod;b>>=1;
	}
	return ans;
}
ll C(ll n,int k){
	if(n<k) return 0;
	ll ans=1;
	for(ll i=n;i>n-k;i--){
		ans=ans*(i%Mod)%Mod;
	}
	return ans*ofra[k]%Mod;
}
int main(){
	o[0]=1,o[1]=-1;
	fra[0]=1;
	for(int i=1;i<=M;i++){
		fra[i]=fra[i-1]*i%Mod;
	}
	ofra[M]=ksm(fra[M],Mod-2);
	for(int i=M;i;i--){
		ofra[i-1]=ofra[i]*i%Mod;
	}
	scanf("%d%lld",&n,&s);
	for(int i=1;i<=n;i++){
		scanf("%lld",&f[i]);
	}
	Ans=C(s+n-1,n-1);
	int k=1<<n;
	for(int i=1;i<k;i++){
		int ty=0;ll tot=0;
		for(int j=0;j<n;j++){
			ty+=(i>>j)&1;
			if((i>>j)&1) tot+=f[j+1]+1;
		}
		Ans=(Ans+o[ty%2]*C(s+n-1-tot,n-1)%Mod)%Mod;
		Ans=(Ans+Mod)%Mod;
	}
	printf("%lld",Ans);
	return 0;
}

综合来看这就是用了一个小技巧和有个小细节的容斥裸题 qwq。
\(\Bbb{End.}\)
\(\Bbb{Thanks} \space \Bbb{For} \space \Bbb{Reading.}\)

posted @ 2021-11-18 22:21  StranGePants  阅读(68)  评论(0编辑  收藏  举报