牛客网【每日一题】4月14日题目精讲 Xorto


传送

时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format:%lld

题目描述

给定一个长度为n的整数数组,问有多少对互不重叠的非空区间,使得两个区间内的数的异或和为0。 输入描述: 第一行一个数n表示数组长度;
第二行n个整数表示数组; 1<=n<=1000,0<=数组元素<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])

题解:

枚举?TLE√
暴力肯定过不了,我们可以先考虑只枚举一个区间[x,y],这个区间可以通过前缀异或和得到。pre来存前缀
我们用[x,y]表示右边的区间,题目要求左右区间异或和为0,也就是问[x,y]左边有多少和它值一样的区间。
我们可以用a[i]来存,a[i]表示左边异或和为i区间个数,数组a反应的数量,i反映的是值。
先将区间[k,i]存进a中,再用a[ ]来查看左边有多少区间异或和值与右区间[i+1 , j]值相同。
因为a存的是数量,所以直接用ans+=a [ pre[i] ^ [j] ]

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7+3;
int a[maxn];
int pre[maxn];
  int x;
    int n;
long long  ans=0;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
	{
        cin>>x;
        pre[i]=pre[i-1]^x;
    }
 
    for(int i=1;i<=n;i++)
	{
       for(int k=0;k<i;k++) a[pre[i]^pre[k]]++;//
       for(int j=i+1;j<=n;j++) ans += a[pre[i]^pre[j]];//
    }
    cout<<ans;
    return 0;
}

扩展

关于异或的题我最近做了个
CF282E Sausage Maximization
牛客网题目链接
异或的题,解法挺新颖,不过不知道为什么牛客网这里不能 提交?
原题是cf的cf题目链接
我自己写的题解

posted @ 2020-04-16 22:55  回归梦想  阅读(63)  评论(0编辑  收藏  举报