先转换成异或前缀和,变成询问两个数异或≥k的方案数。
分治然后Trie树即可。
#include<cstdio> #include<algorithm> #define N 1000010 #define mid (l+r>>1) #define ll long long using namespace std; int n,k,a[N];ll ans; struct Trie { int next[N*30][2],tot,sum[N*30]; void init() { for(int i=1;i<=tot;i++) next[i][0]=next[i][1]=sum[i]=0; tot=1; } void add(int x) { int now=1; for(int i=30;~i;i--) { int c=(x>>i)&1; if(!next[now][c]) next[now][c]=++tot; now=next[now][c]; sum[now]++; } } int query(int x) { int now=1,res=0; for(int i=30;~i;i--) { int c=(k>>i)&1,p=(x>>i)&1; if(c==0)res+=sum[next[now][!p]]; now=next[now][p^c]; if(!now)return res; } return res; } }t; void solve(int l,int r) { if(l==r)return; t.init(); for(int i=l;i<=mid;i++) t.add(a[i]); for(int i=mid+1;i<=r;i++) ans+=t.query(a[i]); solve(l,mid); solve(mid+1,r); } int main() { scanf("%d%d",&n,&k);n++;k--; for(int i=2;i<=n;i++) scanf("%d",&a[i]),a[i]^=a[i-1]; solve(1,n); printf("%lld ",ans); }