题目
给一个序列a[],
每个子区间都要把所有元素相与(and)之后得到一个值v,
求所有v的和
思路来源
https://blog.youkuaiyun.com/lifelikes/article/details/78174268
题解
就是算每一位的贡献,先按二进制压位
这样对于某一位来说,就变成了01序列
1 1 1 0 1 1 1
对于左边的三个1,其贡献为[1,1],[1,2][1,3][2,2][2,3][3,3],共6个区间
即
按位统计贡献即可
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int t,n;
int pos[21][maxn];
ll ans;
int main()
{
scanf("%d",&t);
while(t--)
{
memset(pos,0,sizeof(pos));
ans=0;
scanf("%d",&n);
for(int i=0;i<n;++i)
{
int x,cnt=0;
scanf("%d",&x);
while(x)
{
if(x&1)pos[cnt][i]=1;
cnt++,x>>=1;
}
}
for(int i=0;i<20;++i)
{
ll now=0;
for(int j=0;j<=n;++j)//多一个,清最后的
{
if(pos[i][j]==1)now++;
else
{
ans+=now*(now+1)/2*(1ll<<i);
now=0;
}
}
}
printf("%lld\n",ans);
}
return 0;
}