题目
思路
显然每一个物品是独立的,所以将每一个物品的方案数分别求出来,然后相乘即可。
因为 \(a\leq 100\),所以我们可以枚举最终选择了多少个该物品。假设选择了 \(j\) 个该物品,一共要进行 \(m\) 轮游戏,插板法可以得出
\[ans=\sum^{a_i}_{j=0} \binom{j+m-1}{j}
\]
发现这个组合数中 \(j\) 只有 \(100\),所以可以递推求出。
时间复杂度 \(O(nm\log \operatorname{MOD}+\max(a)·m)\)。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=110,MOD=998244353;
ll n,m,p,ans,sum,C[N][N];
ll fpow(ll x,ll k)
{
ll ans=1;
for (;k;k>>=1,x=x*x%MOD)
if (k&1) ans=ans*x%MOD;
return ans;
}
int main()
{
scanf("%lld%lld",&n,&m);
ans=1;
for (ll i=0;i<=100;i++)
{
C[i][0]=1;
for (ll j=1;j<=min(i+m-1,-1LL+N);j++)
C[i][j]=C[i][j-1]*fpow(j,MOD-2)%MOD*((i+m-1-(j-1))%MOD)%MOD;
}
while (n--)
{
scanf("%lld",&p);
sum=0;
for (int i=0;i<=p;i++)
sum=(sum+C[i][i])%MOD;
ans=ans*sum%MOD;
}
cout<<ans;
return 0;
}