zoukankan      html  css  js  c++  java
  • Leetcode5700. 使所有区间的异或结果为零(DP)

    题意

    (n)个数和一个(k) 可以对一个数任意修改 要求修改最少的数 使得任意连续(k)个数 xor的和等于0
    (a[i] <= 2^{10})

    题解

    显然可以发现一个规律 假如(k=3)修改后的序列都形如(abcabcabc).... 相同字母表示相同的值
    那么可以按(k)分组 (a[i]),(a[i+k]),(a[i+2k])...的分为同一组 同一组的值最后是一样的
    (dp[val])表示已经枚举完了一些组 值为(val)的最小操作次数
    转移有两种

    1)全部修改为一个这组没出现的数

    因为修改成的这个数可以是任意的 所以任意(val)的值都能由前面的最小值来转移过来

    2)全部修改为一个这组出线过的一个数

    依次枚举前面的(val)和选这一组出现过的一个数 单看这里以为总共的复杂度就是 (O(k*k*2^{10})) 就觉得不可做了
    其实就是一个经典错误.. 和树上背包一样 其实复杂度是(O(k* frac{n}{k} *2^{10}))

    class Solution {
    public:
        const int INF = 0x3f3f3f3f;
        int minChanges(vector<int>& nums, int k) {
            int n = nums.size();
            vector<int> dp(1 << 10, INF);
            dp[0] = 0;
            vector<unordered_map<int, int>> g(k);
            vector<int> sz(k);
            for(int i = 0; i < k; i++) {
                for(int j = i; j < n; j += k) {
                    g[i][nums[j]]++;
                    sz[i]++;
                }
            }
            for(int i = 0; i < k; i++) {
                int zx = *min_element(dp.begin(), dp.end());
                vector<int> tmp(1 << 10, zx + sz[i]);
                for(int j = 0; j < (1 << 10); j++) {
                    if(dp[j] == INF) continue;
                    for(auto [a, b] : g[i]) {
                        int nx = a ^ j;
                        tmp[nx] = min(tmp[nx], dp[j] + sz[i] - b);
                    }
                }
                dp = move(tmp);
            }
            return dp[0];
        }
    };
    
  • 相关阅读:
    题解 P2810 【Catch the theives】
    2020.11.27 考试题解
    2020.11.25 考试题解
    题解 SP16254 【RMID2
    2020.11.24 考试题解
    2020.11.23 考试题解
    CSP-2020 T3 函数调用
    二维树状数组学习笔记
    题解 P4910 【帕秋莉的手环】
    Python实现向指定IP的目标机器拷贝文件
  • 原文地址:https://www.cnblogs.com/lwqq3/p/14496058.html
Copyright © 2011-2022 走看看