[ARC107D] Number of Multisets 题解

原题链接

在反复拜读题解对于 DP 式子的解释后终于搞懂了,于是来交一发题解,总结一下心得。因此本篇题解主要针对 DP 式的解释。

题目分析

首先,很明显可以设出一个 $dp_{n,k}$ 的状态表示选择 $n$ 个数和为 $k$。 状态转移如下:

若第 $n$ 个数取 $1$,则有 $dp_{n,k} = dp_{n-1,k-1}$。这点应该还是比较好理解的。

若第 $n$ 个数取分数,因为分数均为 $2$ 的 $-x$ 次幂,可以这样想象:相当于将原来的集合全部乘 $2$,然后选择 $n$ 个数,满足和为 $2k$,然后让新集合的第 $n$ 位做出选择。接着集合全部除回去,我们会惊奇地发现我们选择的第 $n$ 个数恰好不等于 $1$ 且同样是 $2$ 的 $-x$ 次幂。

即 $dp_{n,k} = dp_{n,2 \times k}$。

最终的 $dp_{n,k}$ 为上述两种情况的和。 即 $dp_{n,k} = dp_{n,2 \times k} + dp_{n-1,k-1}$。

再处理一下边界条件 $dp_{0,0} = 1$ 和一些小细节就搞定了!

#include<bits/stdc++.h>
using namespace std;
//记得开两倍N
const int N = 6005,mod = 998244353;
int dp[N][N],n,k;
int main()
{
    scanf("%d%d",&n,&k);
    dp[0][0] = 1;// 边界条件
    for (int i = 1;i <= n;i++)
        for (int j = i;j >= 1;j--) // 转移,由于需要先得出dp[i][j*2],所以倒序枚举。
            dp[i][j] += dp[i-1][j-1] % mod + dp[i][j*2] % mod,dp[i][j] %= mod;
    cout << dp[n][k] << endl;
    return 0;
}
posted @ 2023-10-28 17:29  codwarm  阅读(21)  评论(0)    收藏  举报  来源