1 条题解
-
0
dp[i + 1][j] 表示对于前 (i+1) 个整数,和为 j 是否能够实现的状态。这个状态由前 i 个整数是否能够实现状态 j,以及第 i+1 个整数是否能够与状态 j 或 (j-nums[i]%k+k)%k 实现状态 j 而来。这两种情况只要有一种成立,就说明在前 (i+1) 个整数中存在一种组合,可以得到状态 j。
j 表示和的余数,范围在 0 到 k-1 之间,因为我们关心的是和除以 k 的余数,所以状态数组是一个二维数组,行表示前 i+1 个整数,列表示和的余数。
dp[i][(j+nums[i])%k] 表示使用前 i 个整数可以实现状态 (j+nums[i])%k。这里 (j+nums[i])%k 表示将第 i+1 个整数加到前 i 个整数的和中,然后对 k 取余,得到新的余数。
dp[i][(j-nums[i]%k+k)%k] 表示使用前 i 个整数可以实现状态 (j-nums[i]%k+k)%k。这里 (j-nums[i]%k+k)%k 表示将第 i+1 个整数从前 i 个整数的和中减去,然后加 k 取余,得到新的余数。
dp[i + 1][j] 是两种情况的逻辑或操作结果,只要其中一种情况成立,就能够实现状态 j。如果 dp[i + 1][j] 为 true,说明前 (i+1) 个整数可以实现状态 j,否则为 false。
这个状态转移方程考虑了前 i+1 个整数是否可以实现所有可能的状态 j,最后的结果就是判断是否至少存在一个状态 j 可以被整数 k 整除
#include <bits/stdc++.h> using namespace std; int main() { int N, k; cin >> N >> k; vector<int> nums(N); for (int i = 0; i < N; i++) { cin >> nums[i]; } vector<vector<bool>> dp(N + 1, vector<bool>(k, false)); dp[0][0] = true; for (int i = 0; i < N; i++) { // 修改循环起始位置 for (int j = 0; j < k; j++) { dp[i + 1][j] = dp[i][(j+nums[i])%k] || dp[i][(j-nums[i]%k+k)%k]; // 修改状态转移方程 } } if (dp[N][0]) { // 修改判断条件 cout << "YES" << endl; } else { cout << "NO" << endl; } return 0; }
- 1
信息
- ID
- 675
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者