【bzoj4710】[Jsoi2011]分特产
作者:互联网
JYY 带队参加了若干场ACM/ICPC 比赛,带回了许多土特产,要分给实验室的同学们。
JYY 想知道,把这些特产分给N 个同学,一共有多少种不同的分法?当然,JYY 不希望任何一个同学因为没有拿到特产而感到失落,所以每个同学都必须至少分得一个特产。
例如,JYY 带来了2 袋麻花和1 袋包子,分给A 和B 两位同学,那么共有4 种不同的分配方法:
A:麻花,B:麻花、包子
A:麻花、麻花,B:包子
A:包子,B:麻花、麻花
A:麻花、包子,B:麻花
输入
输入数据第一行是同学的数量N 和特产的数量M。
第二行包含M 个整数,表示每一种特产的数量。
N, M 不超过1000,每一种特产的数量不超过1000
输出
输出一行,不同分配方案的总数。由于输出结果可能非常巨大,你只需要输出最终结果 MOD 1,000,000,007 的数值就可以了。
样例输入
5 4
1 3 3 5
样例输出
384835
由于“每个同学都必须至少分得一个特产”这个限制比较难处理,所以我们可以考虑容斥,
用没有限制-至少1个人没分到+至少2个人没分到-... 得到答案。
考虑如果i个人没分到该怎么处理:n个人选出i个不分,方案数为C(n,i);
对于每种特产设有w[i]个,分给(n−i)个同学,允许有人拿不到,方案数为
c(w[i]+n-i-1,n-i-1)
故最终答案为∑(-1)^i * C(n,i) *∑C(w[j]+n-i-1,n-i-1) (0<=i<=n-1,1<=j<=m)
手动算一下
3 2
3 4
则没有限制的有c(3,0)*c(5,2)*C(6,2)=150
至少有一个人没拿到C(3,1)*C(4,1)*C(5,1)=60
至少有二个人没拿到C(3,2)*1*1=3
ans=150-60+3=93
#include <bits/stdc++.h> #define N 2010 using namespace std; typedef long long ll; const ll mod = 1000000007; ll c[N][N]; int w[N]; int main() { int n , m , i , j; ll ans = 0 , tmp; for(i = 0 ; i <= 2000 ; i ++ ) { c[i][0] = 1; for(j = 1 ; j <= i ; j ++ ) c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod; } scanf("%d%d" , &n , &m); for(i = 1 ; i <= m ; i ++ ) //M个特产 scanf("%d" , &w[i]); for(i = 0 ; i < n ; i ++ ) { tmp = c[n][i]; // cout<<" i is "<<i<<endl; for(j = 1 ; j <= m ; j ++ ) { tmp = tmp * c[ w[j] + n - i - 1] [w[j]] % mod; // cout<<" m iss "<<c[ w[j] + n - i - 1] [w[j]]<<endl; } // cout<<i<<" tmp is "<<tmp<<endl; if(i & 1) ans = (ans - tmp + mod) % mod; else ans = (ans + tmp) % mod; // cout<<i<<" ans is "<<ans<<endl; } printf("%lld\n" , ans); return 0; }
标签:同学,Jsoi2011,麻花,ll,特产,JYY,bzoj4710,包子 来源: https://www.cnblogs.com/cutemush/p/11906165.html