NC14247 Xorto

题目

题目描述

给定一个长度为 \(n\) 的整数数组,问有多少对互不重叠的非空区间,使得两个区间内的数的异或和为 \(0\)

输入描述

第一行一个数 \(n\) 表示数组长度;
第二行 \(n\) 个整数表示数组;
\(1 \leq n \leq 1000\), \(0\leq 数组元素 < 100000\)

输出描述

一行一个整数表示答案。

示例1

输入

3
0 0 0

输出

5

说明

([1,1],[2,2]),([1,1],[3,3]),([1,1],[2,3]),([1,2],[3,3]),([2,2],[3,3])

题解

知识点:前缀和,枚举。

注意到区间是不重合但长度不定,考虑枚举左区间的右端点 \(i\) 。对于某个左区间右端点 \(i\) ,枚举左区间左端点 \(j\) ,左区间可能被右区间重复匹配,考虑利用数组 \(cnt\) 记录某个异或值的左区间个数;对于某个左区间右端点 \(i\) ,固定右区间左端点为 \(i+1\), 枚举右区间的右端点 \(j\) ,与之前记录的 \(cnt\) 进行匹配。

时间复杂度 \(O(n^2)\)

空间复杂度 \(O(1)\)

代码

#include <bits/stdc++.h>

using namespace std;

int a[1007],cnt[2*100000+7];

int main(){
    std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int n;
    cin>>n;
    for(int i = 1;i<=n;i++){
        cin>>a[i];
        a[i] ^= a[i-1];
    }

    long long ans = 0;///O(n^4)空间 大概1x10^12>2*10^9
    for(int i = 1;i<=n;i++){///向左遍历左区间的右端点i。对于一组相同端点的左区间,一定会被其右端点往后的点作为左端点的右区间遍历匹配,因此每次处理都保留
        for(int j = 1;j<=i;j++){///遍历以i为右端点的左区间的左端点
            cnt[a[i]^a[j-1]]++;
        }
        for(int j = i+1;j<=n;j++){///遍历以i+1为左端点的右区间的右端点
            ans+=cnt[a[j]^a[i]];
        }
    }
    cout<<ans<<'\n';
    return 0;
}
posted @ 2022-05-09 11:21  空白菌  阅读(20)  评论(0编辑  收藏  举报