CF1957D 题解
题意
定义
思路
展开式子,得到
考虑
考虑证明,显然
那么需要快速求出某一位为
如此
代码
#include<iostream>
#include<cmath>
#define int long long
using namespace std;
const int N=1e5+10;
const int K=30+10;
int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar();}
while(ch>='0'&&ch<='9') { s=s*10+ch-'0'; ch=getchar();}
return s*w;
}
int T,n,ans,a[N],b[N],s[N][K],h[N];//h[i]表示a[i]的最高位,其余如上述
signed main()
{
T=read();
while(T--)
{
n=read(),ans=0;
for(int i=1;i<=n;i++) a[i]=read(),b[i]=b[i-1]^a[i],h[i]=floor(log2(a[i]));
for(int i=1;i<=n;i++)
{
for(int j=0;j<=30;j++) s[i][j]=s[i-1][j];
int ct=0;
while(b[i])
{
if(b[i]&1) s[i][ct]++;
b[i]>>=1,ct++;
}
}//按思路维护各数组
for(int i=1;i<=n;i++)
{
int ta=s[i-1][h[i]],tb=s[n][h[i]]-s[i-1][h[i]];//b[x-1]与b[z]同为1的数量
int tc=i-ta,td=n-i+1-tb;//同为0的数量,注意x=1时b[0]也要考虑进去
ans+=ta*tb+tc*td;//统计方案数
}
cout<<ans<<'\n';
}
return 0;
}