为什么多重背包不二进制优化能过,二进制优化会 WA。

代码(优化):

#include <bits/stdc++.h>
using namespace std;
#define N 10005

int n, k, dp[N];

int main() {
	scanf("%d%d", &k, &n); dp[0] = 1;
	for (int i = 0; (1 << i) <= n; i++)
		for (int cnt = 1; cnt * (1 << i) <= n && cnt <= k; cnt <<= 1)
			for (int j = n; j >= cnt * (1 << i); j--)
				dp[j] = (dp[j] + dp[j - cnt * (1 << i)]) % 1000000007;
	printf("%d\n", dp[n]);
	return 0;
}

不优化:

#include <bits/stdc++.h>
using namespace std;
#define N 10005

int n, k, dp[N];

int main() {
	scanf("%d%d", &k, &n); dp[0] = 1;
	for (int i = 0; (1 << i) <= n; i++)
		for (int j = n; j; j--)
		    for (int cnt = 1; cnt <= k && cnt * (1 << i) <= j; cnt++)
				dp[j] = (dp[j] + dp[j - cnt * (1 << i)]) % 1000000007;
	printf("%d\n", dp[n]);
	return 0;
}

3 条评论

  • @ 2026-10-4 12:09:38

    你的二进制写的有问题。 例如 i = 0, n = 3, K = 2, cnt 可以枚举到 1, 2。 那么程序就会计算 1+21 + 2 这种情况,实际上是不合法的。

    但是,即使是正确的二进制拆分也会 wa。

    • @ 2026-10-3 9:00:13

      学到了

      • @ 2026-10-2 12:00:39

        计数类多重背包是不能随便优化的。

        参考之前讲过的那个硬币的问题。

        • 1

        信息

        ID
        2771
        时间
        ms
        内存
        MiB
        难度
        5
        标签
        (无)
        递交数
        19
        已通过
        8
        上传者