Skip to main content
Back to problems
#1787
Hard Algorithms

Make the xor of all segments equal to zero

Array Hash Table Dynamic Programming Bit Manipulation Counting
41.0% acceptance
Mar 1, 2026
424
27
You are given an array nums and an integer k. Return the minimum number of elements to change so that the XOR of all segments of size k equals zero.

Solution

Rust
Time O(n * m)
Space O(n * m)
LeetCode
solution.rs
impl Solution {
  pub fn min_changes(nums: Vec<i32>, k: i32) -> i32 {
    let n = nums.len();
    let k = k as usize;
    let max_val = 1024usize;

    // Group nums by index mod k
    let mut groups: Vec<Vec<i32>> = vec![vec![]; k];
    for (i, &v) in nums.iter().enumerate() {
      groups[i % k].push(v);
    }

    // dp[x] = min changes to make XOR of chosen values for groups 0..i equal x
    let mut dp = vec![n as i32; max_val];
    dp[0] = 0;

    for group in &groups {
      let group_size = group.len() as i32;
      let mut freq = vec![0i32; max_val];
      for &v in group {
        freq[v as usize] += 1;
      }
      // Only iterate over values that actually appear in this group.
      // Complexity per group: O(max_val * distinct_vals) instead of O(max_val^2).
      let distinct: Vec<(usize, i32)> = (0..max_val)
        .filter(|&v| freq[v] > 0)
        .map(|v| (v, freq[v]))
        .collect();

      let global_min = *dp.iter().min().unwrap();
      let base = global_min + group_size;
      let prev_dp = dp.clone();
      dp = vec![base; max_val];

      for prev_x in 0..max_val {
        // Skip if no transition from prev_x can beat the base cost.
        if prev_dp[prev_x] >= base { continue; }
        for &(v, fv) in &distinct {
          let new_x = prev_x ^ v;
          let cost = prev_dp[prev_x] + group_size - fv;
          if cost < dp[new_x] {
            dp[new_x] = cost;
          }
        }
      }
    }
    dp[0]
  }
}