1 条题解

  • 0
    @ 2024-2-28 15:00:24

    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
    上传者