洛谷 P9236:异或和之和

【题目来源】
https://www.luogu.com.cn/problem/P9236

【题目描述】
给定一个数组 Ai,分别求其每个子段的异或和,并求出它们的和。或者说,对于每组满足 1≤L≤R≤n 的 L,R,求出数组中第 L 至第 R 个元素的异或和。然后输出每组 L,R 得到的结果加起来的值。

【输入格式】
输入的第一行包含一个整数 n 。
第二行包含 n 个整数 Ai,相邻整数之间使用一个空格分隔。

【输出格式】
输出一行包含一个整数表示答案。

【输入样例】
5
1 2 3 4 5

【输出样例】
39

【数据范围】
对于 30% 的评测用例,n≤300;
对于 60% 的评测用例,n≤5000;
对于所有评测用例,1≤n≤10^5,0≤Ai≤2^20。

【算法分析】
● 异或运算的基本性质
异或运算(XOR)具有以下重要性质:
交换律‌:a ^ b = b ^ a
结合律‌:a ^ (b ^ c) = (a ^ b) ^ c
自反性‌:a ^ a = 0
零元素‌:a ^ 0 = a
可逆性‌:如果 a ^ b = c,那么 a = c ^ b

● 前缀异或和重要性质
求证:若定义前缀异或和 s[i]=a[0]^a[1]^a[2]^…^a[i],则子区间 [le,ri] 的异或和等于 s[ri]^s[le−1]。
证明:由前缀异或和的定义,知:
s[ri] = a[0]^a[1]^a[2]^…^a[ri],s[le−1] = a[0]^a[1]^a[2]^…^a[le−1]。
所以 s[ri]^s[le−1] = (a[0]^a[1]^…^a[ri]) ^ (a[0]^a[1]^…^a[le−1])
= (a[0]^a[1]^…^a[le−1]) ^ (a[0]^a[1]^…^a[le−1]^a[le]^…^a[ri])
= (a[0]^a[1]^…^a[le−1]) ^ (a[0]^a[1]^…^a[le−1]) ^ (a[le]^…^a[ri])
= 0 ^ (a[le]^…^a[ri])= a[le]^…^a[ri]
又已知区间 [le,ri] 的异或和等于 a[le]^…^a[ri]。
综上,得证。

【算法代码】

#include <bits/stdc++.h>
using namespace std;

const int maxn=1e5+5;
int a[maxn],s[maxn];
int n;

int main() {
    cin>>n;
    for(int i=1; i<=n; i++) {
        cin>>a[i];
        s[i]=s[i-1]^a[i];
    }

    long long ans=0;
    for(int i=1; i<=n; i++) { //prefix XOR sum of [i,j]
        for(int j=i; j<=n; j++) {
            ans+=(s[i-1]^s[j]);
        }
    }
    cout<<ans<<endl;

    return 0;
}

/*
in:
5
1 2 3 4 5

out:
39
*/

 

 

【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/154304346
https://www.luogu.com.cn/problem/solution/P9236
https://blog.csdn.net/lxr_lxr_/article/details/150269308

 

posted @ 2025-11-03 09:06  Triwa  阅读(4)  评论(0)    收藏  举报