[ARC107D] Number of Multisets
传送门
Problem Statement
You are given two positive integers N N N and K K K. How many multisets of rational numbers satisfy all of the following conditions?
- The multiset has exactly N N N elements and the sum of them is equal to K K K.
- Each element of the multiset is one of 1 , 1 2 , 1 4 , 1 8 , … 1, \frac{1}{2}, \frac{1}{4}, \frac{1}{8}, \dots 1,21,41,81,…. In other words, each element can be represented as 1 2 i ( i = 0 , 1 , … ) \frac{1}{2^i}\ (i = 0,1,\dots) 2i1 (i=0,1,…).
The answer may be large, so print it modulo 998244353 998244353 998244353.
Constraints
- 1 ≤ K ≤ N ≤ 3000 1 \leq K \leq N \leq 3000 1≤K≤N≤3000
- All values in input are integers.
Input
Input is given from Standard Input in the following format:
N K
Output
Print the number of multisets of rational numbers that satisfy all of the given conditions modulo 998244353 998244353 998244353.
Sample Input 1
4 2
Sample Output 1
2
The following two multisets satisfy all of the given conditions:
- 1 , 1 2 , 1 4 , 1 4 {1, \frac{1}{2}, \frac{1}{4}, \frac{1}{4}} 1,21,41,41
- 1 2 , 1 2 , 1 2 , 1 2 {\frac{1}{2}, \frac{1}{2}, \frac{1}{2}, \frac{1}{2}} 21,21,21,21
Sample Input 2
2525 425
Sample Output 2
687232272
题目翻译
给出两个正整数 N N N, K K K。求有多少有理数集满足以下所有条件:
- 集合有且只有 N N N 个元素,并且元素和为 K K K;
- 每个元素须可表示为 1 2 i ( i ∈ N ) \frac {1}{2^{i}}(i\in N) 2i1(i∈N)。
答案可能很大,请将其对 998244353 998244353 998244353 取 mod。
注明
以上来自 A t c o d e r ,翻译来源:洛谷。 以上来自 Atcoder,翻译来源:洛谷。 以上来自Atcoder,翻译来源:洛谷。
解题思路
非常容易想到 DP。用 D P i , j DP_{i,j} DPi,j 表示选了 i i i 个数,和为 j j j 的情况。由题意可知,选的数只能是 2 − x , x ∈ N 2^{-x},x \in N 2−x,x∈N,所以一定满足 i ≥ j i \geq j i≥j。
考虑如何转移:
- 显然,边界为 D P 0 , 0 = 0 DP_{0,0}=0 DP0,0=0;
- 若选 1 1 1 放入,则显然有 D P i , j = D P i − 1 , j − 1 DP_{i,j}=DP_{i-1,j-1} DPi,j=DPi−1,j−1;
- 若选 2 − x , x ∈ N + 2^{-x},x \in N_{+} 2−x,x∈N+ 放入,可以考虑将原先选的数乘 2 2 2,在加上 一个数使得满足和为 2 × k 2 \times k 2×k(C Wx:在序列末尾加上一个 1 1 1,再将整个序列除以 2 2 2),得出 D P i , j + = D P i , j × 2 , j × 2 ≥ 0 DP_{i,j}+=DP_{i,j \times 2},j \times 2 \geq 0 DPi,j+=DPi,j×2,j×2≥0。
(C Wx:注意一定要讲这题的坑点!)
注意:
j
j
j 要从大到小处理,因为要先求出
j
j
j 较小时的
D
P
i
,
j
×
2
DP_{i,j \times 2}
DPi,j×2 的值。
AC Code
#include<bits/stdc++.h>
using namespace std;
int N, K;
int DP[5005][5005];
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0), cin >> N >> K, DP[0][0] = 1;
for (register int i = 1; i <= N; ++i) for (register int j = i; j >= 1; j--) {
DP[i][j] = DP[i - 1][j - 1];
if ((j << 1) <= i) DP[i][j] = (DP[i][j] + DP[i][j << 1] > 998244353 ? DP[i][j] + DP[i][j << 1] - 998244353 : DP[i][j] + DP[i][j << 1]);
}
cout << DP[N][K] << endl;
return 0;
}
(C Wx:我用滚动数组跑出了最优解!)