[luogu P5505] [JSOI2011]分特产

我丢 : https://www.luogu.com.cn/problem/P5505

思路 & 题解

可以转换为求它的补集
设 f [ i ] 为 恰 好 i 个 人 没 有 特 产 的 方 案 数 设f[i]为恰好i个人没有特产的方案数 f[i]i
设 g [ i ] 为 钦 定 i 个 人 没 有 特 产 的 方 案 数 设g[i]为钦定i个人没有特产的方案数 g[i]i
答案就是 f [ 0 ] f[0] f[0]直接套二项式反演即可
g [ i ] g[i] g[i]的使用用插板法
code:

#include<bits/stdc++.h>
#define N 3005
#define mod 1000000007
#define int long long
using namespace std;
int c[N][N], f[N], a[N], n, m;
signed main() {
	for(int i = 0; i < N; i ++) c[i][0] = 1;
	for(int i = 1; i < N; i ++)
		for(int j = 1; j <= i; j ++)
			c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
			
	scanf("%lld%lld", &n, &m);
	for(int i = 1; i <= m; i ++) scanf("%lld", &a[i]);
	for(int i = 0; i <= n; i ++) f[i] = c[n][i];
	for(int i = 0; i <= n; i ++)
		for(int j = 1; j <= m; j ++) 
			f[i] = f[i] * c[n - i - 1 + a[j]][n - i - 1] % mod;
	
	int ans = 0;
	for(int i = 0; i <= n; i ++)
		ans = (ans + (i & 1? -1 : 1) * c[i][0] * f[i] + mod) % mod;
	
	printf("%lld\n", ans);
	
	return 0;
}
posted @ 2020-05-11 17:34  lahlah  阅读(32)  评论(0编辑  收藏  举报