1. 程式人生 > 實用技巧 >【SSLOJ1519】揹包簽到題

【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;
}