【AtCoder思维训练】ABC221H Count Multiset
Preface
一道比较容易的前缀和优化 dp 题目。
Problem
输入两个正整数
一个合法的集合定义指长度为
Solution
首先,经典套路,集合转不下降序列。
不下降序列转差分。
设
并且,由于对元素和的性质,根据差分得到:
由于这个限制内带
现在这个限制就非常的好,可以开始进行 dp 了。
容易设状态为
容易列出状态转移方程:
其中,
显然,第二个
总复杂度为
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5010;
const int mod=998244353;
int n,m,f[N][N],sum[N];
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n>>m;
f[0][0]=1;sum[0]=1;
for(int p=1;p<=n;p++){
for(int j=1;j<=n;j++){
for(int i=1;i*p<=j;i++){
f[p][j]+=sum[j-p*i];
f[p][j]%=mod;
}
}
for(int j=0;j<=n;j++){
if(p-m>=0)sum[j]=(sum[j]-f[p-m][j]+mod)%mod;
sum[j]=(sum[j]+f[p][j])%mod;
}
}
for(int i=1;i<=n;i++)
cout<<f[i][n]<<"\n";
return 0;
}