题解:奖品分配 [GESP8级]
2025-12-27 10:44:39
发布于:山东
20阅读
0回复
0点赞
发现对于多出来的一个礼物的方案数其实和原问题是相同的(排n+1个然后只取前n个就好了),所以如果礼物多了就把总人数+1
思路一:考虑对于每一类依次分配,因为同种奖品视作相同,所以用组合数来放奖品,再根据乘法原理乘起来就是答案了(因为本质上小朋友的顺序也是无关的)
别忘了每放完一类之后要把这一类放的个数从总人数里减去
ans=C(n,a[1])*C(n-a[1],a[2])*C(n-a[1]-a[2],a[3])*...*C(n-a[1]-a[2]-...-a[n-1],a[n])
思路二:这可以看作是可重集合的排列问题(即求的是排列,但中间有不同元素视作同种的情况),有公式:
ans = n! / (a[1]! * a[2]! * ... * a[n]!)
// 思路二
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1005, P = 1e9 + 7;
ll a[N], fac[N], ifac[N];
ll Pow(ll x, ll y){
ll ans = 1;
while(y){
if(y & 1) ans = ans * x % P;
x = x * x % P; y >>= 1;
}
return ans;
}
void solve()
{
int n, m; cin >> n >> m;
ll sum = 0;
for(int i = 1; i <= m; i ++){
cin >> a[i]; sum += a[i];
}
ll inv = 1;
for(int i = 1; i <= m; i ++){
inv = inv * ifac[a[i]] % P;
}
cout << fac[sum] * inv % P << '\n';
}
signed main()
{
ios :: sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
fac[0] = 1;
for(int i = 1; i < N; i ++){
fac[i] = fac[i - 1] * i % P;
}
ifac[N - 1] = Pow(fac[N - 1], P - 2);
for(int i = N - 2; i >= 0; i --){
ifac[i] = ifac[i + 1] * (i + 1) % P;
}
int T; cin >> T;
while(T --) solve();
return 0;
}
这里空空如也




有帮助,赞一个