【SSLOJ1519】背包签到题

题目

思路

显然每一个物品是独立的,所以将每一个物品的方案数分别求出来,然后相乘即可。
因为 \(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;
}
原文地址:https://www.cnblogs.com/stoorz/p/13663134.html