前言:

是我为数不多自己做出来的紫题吧..(但是也给了我很多警醒--一定要想清楚再写代码.)

思维:

这题思路不复杂.它要你计数,那你就按照它给的去计数就好了,把异或的前缀存起来,这样的好处就是你每次异或的时候鸭,它就是一个二元组.然后放字典树上模拟就好了...(为什么我要debug那么久啊!

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+500,M=2e7; 
ll pre[N];
int son[M][2];//当前节点子节点是0/1的节点是哪个. 
int id=1,p;int num[M];//统计下这个位节点有多少. 
void insert(ll x)
{
    p=0;
    for(ll i=31;i>=0;i--)
    {
        ll pos=(x>>i&1);
        int &s=son[p][pos];
        if(!s) s=id++;
        num[s]++;
        p=s;
    }
}

ll cal(ll x,ll k)
{
    p=0;int wz;ll Res=0;
    for(ll i=31;i>=0;i--)
    {
        ll pos=(x>>i&1);
        ll res=(k>>i&1);
        if(res==1)
        {
            wz=!pos;
            if(i==0)    Res+=num[son[p][!pos]];
        }
        else
        {
            wz=pos;
            if(son[p][!pos])    Res+=num[son[p][!pos]];
            if(i==0)            Res+=num[son[p][pos]];
        }int &s=son[p][wz];if(!s)    break;
        p=s;
    }return Res;
}

int main()
{
    int n;ll k,ans=0;
    scanf("%d%lld",&n,&k);//最高位最多是31
    for(int i=1;i<=n;i++)
    {
        pre[i]^=pre[i-1];
        int x;scanf("%d",&x);
        pre[i]^=x;
        ans+=cal(pre[i],k);
        if(pre[i]>=k)    ans++;    
        insert(pre[i]);
    }printf("%lld\n",ans);
    return 0;
}