C/C++ Group A Question H of the 14th Lanqiao Cup Provincial Competition - XOR and Sum (AC)

1. XOR and sum

1. Description of the topic

Given an array A i A_iAi, find the XOR sum of each of its sub-segments, and find their sum. In other words, for each group satisfying 1 ≤ L ≤ R ≤ n 1 \leq L \leq R \leq n1LRn L, RL , RL,R , find theLLthL toRRXOR sum of R elements. Then output each set ofL , RL, RL,The sum of the results obtained by R.

2. Input format

The first line of input contains an integer nnn

The second line contains nnn integersA i A_iAi, separated by a space between adjacent integers.

3. Output format

Output a line containing an integer representing the answer.

4. Sample input

5
1 2 3 4 5

5. Sample output

39

6. Data range

For 30% 30\%30% of the evaluation cases,n ≤ 300 n \leq 300n300

For 60 % 60\%60% of the evaluation cases,n ≤ 5000 n \leq 5000n5000

For all evaluation cases, 1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^51n105 0 ≤ A i ≤ 2 20 0 \leq A_i \leq 2^{20} 0Ai220

7. Link to the original title

XOR and sum

2. Problem-solving ideas

First, violently enumerate each subinterval [ l , r ] [l,r] according to the meaning of the question[l,r] ( 1 ≤ l ≤ r ≤ n ) (1\leq l \leq r \leq n) (1lrn ) , the complexity will beO ( n 2 ) O(n^2)O ( n2 ), can't pass this question, but can get a certain score.

Since an XOR operation is involved and observing ai a_iaiThe range of values ​​is [ 0 , 2 20 ] [0,2^{20}][0,220 ], it is not difficult for us to think about the problem from the perspective of "disassembly". Assume that for the i-th ∈ [ 0 , 20 ] i \in[0,20]of the binary biti[0,20 ] bits, there arexxThe XOR sum of the x sub-intervals at this bit is1 11 , then the contribution of this bit to the answer is2 i × x 2^{i} \times x2i×x . In this way, we split the whole big problem into20 2020 sub-questions, the original array is equivalent to being split into 20 20by us20 010101 array.

For each subquestion, that is, for each 01 0101 array, we need to find out how many sub-arrays whose XOR sum is1 11 , that is to find the xxmentioned abovex . We can solve this problem by prefix XOR. Set here01 0101 array isaaa array, we set anotherSSS pairs,S i S_iSimeans aaa array beforeiiWhat is the XOR sum of i elements. According to the nature of the XOR operation:

a i ⊕ a i + 1 ⊕ ⋯ ⊕ a j − 1 ⊕ a j = ( a 1 ⊕ a 2 ⊕ ⋯ a j ) ⊕ ( a 1 ⊕ a 2 ⊕ ⋯ ⊕ a i − 1 ) a_i \oplus a_{i+1} \oplus \cdots \oplus a_{j-1} \oplus a_j=(a_1 \oplus a_2 \oplus \cdots a_j) \oplus (a_1 \oplus a_2 \oplus \cdots \oplus a_{i-1}) aiai+1aj1aj=(a1a2aj)(a1a2ai1)

Apply the above formula to SSS is replaced with:

a i ⊕ a i + 1 ⊕ ⋯ ⊕ a j − 1 ⊕ a j = S i − 1 ⊕ S j a_i \oplus a_{i+1} \oplus \cdots \oplus a_{j-1} \oplus a_j=S_{i-1} \oplus S_j aiai+1aj1aj=Si1Sj

If you want to make the left side of the equation equal to 1 11 , which meansS i − 1 ≠ S j S_{i-1} \ne S_jSi1=Sj

According to the above analysis, we can enumerate each 01 0101 The prefix XOR arraySSS , when we enumerate toS j S_jSj, we only need to consider how many S i S_i before itSiUnlike it, the different numbers are equal to aj a_jajend and XOR sum is 1 1The number of sub-arrays of 1 , we can use the hash table to realize the function of counting the number.

This way we can run in close to O ( n ) O(n)The complexity of O ( n ) counts each01 0101 Array sub-interval XOR is1 1The number of 1 , we set theii01 01 of i binary digits01 Array sub-interval XOR is1 1The number of 1 isbi b_ibi, the final answer is:

∑ i = 0 20 2 i × b i \sum_{i=0}^{20} 2^{i} \times b_i i=0202i×bi

Time complexity: O ( 20 × n ) O(20 \times n)O(20×n)

3. AC_Code

  • C++
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 100010;

int n;
int a[N][25];
int main()
{
    
    
	ios_base :: sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; ++i) {
    
    
		int x;
		cin >> x;
		for (int j = 0; j <= 20; ++j) {
    
    
			a[i][j] = (x >> j) & 1;
			a[i][j] ^= a[i - 1][j];
		}
	}
	LL ans = 0;
	for (int j = 0; j <= 20; ++j) {
    
    
		map<int, int> m;
		m[0]++;
		for (int i = 1; i <= n; ++i) {
    
    
			int x = m[a[i][j] ^ 1];
			ans += 1LL * (1 << j) * x;
			m[a[i][j]]++;
		}
	}
	cout << ans << '\n';
	return 0;
}
  • Java
import java.util.*;

public class Main {
    
    
    static final int N = 100010;

    public static void main(String[] args) {
    
    
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int[][] a = new int[N][25];
        for (int i = 1; i <= n; ++i) {
    
    
            int x = scan.nextInt();
            for (int j = 0; j <= 20; ++j) {
    
    
                a[i][j] = (x >> j) & 1;
                a[i][j] ^= a[i - 1][j];
            }
        }
        long ans = 0;
        for (int j = 0; j <= 20; ++j) {
    
    
            Map<Integer, Integer> m = new HashMap<>();
            m.put(0, 1);
            for (int i = 1; i <= n; ++i) {
    
    
                int x = m.getOrDefault(a[i][j] ^ 1, 0);
                ans += (1L << j) * x;
                m.put(a[i][j], m.getOrDefault(a[i][j], 0) + 1);
            }
        }
        System.out.println(ans);
    }
}
  • Python
n = int(input())
N = 100010
a = [[0] * 25 for _ in range(N)]
b = list(map(int, input().split()))
for i in range(1, n + 1):
    x = b[i-1]
    for j in range(21, -1, -1):
        a[i][j] = (x >> j) & 1
        a[i][j] ^= a[i - 1][j]
ans = 0
for j in range(21, -1, -1):
    m = {
    
    0: 1}
    for i in range(1, n + 1):
        x = m.get(a[i][j] ^ 1, 0)
        ans += (1 << j) * x
        m[a[i][j]] = m.get(a[i][j], 0) + 1
print(ans)

Guess you like

Origin blog.csdn.net/m0_57487901/article/details/131712490