这道题开始写的时候让我想起了子段异或这道题
https://ac.nowcoder.com/acm/contest/3005/D
思路:首先你需要知道 0^x=x ; x^x=0
数据比较小(枚举啦)(我太菜了orz)
所以接下来我们枚举一个区间(求出他的异或和)然后找到其他区间(不重叠)是否存在和此前区间一样的异或和值( x^x=0嘛) 枚举一条线将总区间分成两个区间 例如{a1,a2,a3,a4,a5}
从a1开始分成{a1}{a2,a3,a4,a5}
{a2} {a2,a3} {a2,a3,a4} {a2,a3,a4,a5}
{a3} {a3,a4} {a3,a4,a5}
这是下面代码里面的枚举法

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1007;
ll a[maxn];
ll b[maxn];///异或前缀和数组
map<ll,ll>M;///记录每个子段的异或值
int main()
 {
     ll n;
     scanf("%lld",&n);
     memset(a,0,sizeof(a));
     memset(b,0,sizeof(b));
     for (int i=1;i<=n;++i)
     {
          scanf("%lld",a+i);
          b[i]=b[i-1]^a[i];///0异或任何数都是本身,
     }
     ll ans=0;
     for (ll  i=1;i<=n;++i)///从左向右枚举
     {
          int w=0;
          for (ll  j=i;j>=1;--j)
          {
              w^=a[j];///从一个值枚举到以1-j的各个子集的异或和
              M[w]++;///储存子集异或和
          }
          w=0;
          for (ll k=i+1;k<=n;++k)
          {
              w=w^a[k];///枚举从i+1到n的子集 不会重叠因为每次异或值中的a[i]不同
              ans+=M[w];///加上满足条件的子集
          }
     }
     printf("%lld",ans);
     return 0;
}

当然可以用前缀和记录
i-j的子段用M[i-1]^M [j]就行

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1007;
ll a[maxn];
ll b[maxn];///异或前缀和数组
map<ll,ll>M;///记录每个子段的异或值
int main()
 {
     ll n;
     scanf("%lld",&n);
     memset(a,0,sizeof(a));
     memset(b,0,sizeof(b));
     for (int i=1;i<=n;++i)
     {
          scanf("%lld",a+i);
          b[i]=b[i-1]^a[i];///0异或任何数都是本身,
     }
     ll ans=0;
     ll w=0;
     for (ll i=1;i<=n;++i)
     {
         for (int j=i;j>=1;--j)
         {
             M[b[i]^b[j-1]]++;///枚举1到n
         }
         for (int k=i;k<=n-1;++k)
         {
             ans+=M[b[k+1]^b[i]];///从i+1例举到n
         }
     }
     printf("%lld",ans);
     return 0;
}