链接: http://codeforces.com/problemset/problem/1030/E
思路: 如果区间[ L, R ] 想要满足good ,那么充分必要条件就是 1 [ L, R ] 的每一位1 的个数和是偶数, 2 [ L, R ]中的二进制1 最多的一个数的1 的个数的2倍不能超过sum 。 那么一个 longlong 的数,二进制1 最多 64 (1e18 62),那么我只要向前枚举到他的二倍就可以了,剩下的我可以用 前缀和来转移。 odd[ i ] 表示 [1,x] (x<=i) 的二进制和为奇数的数量。even 同理
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =3e5+5;
int even[N];
int odd[N];
int sum[N];
int n;
int a[N];
int zhuan(ll x)
{
int cnt=0;
while(x)
{
if(x%2) cnt++;
x/=2;
}
return cnt;
}
int main()
{
scanf("%d",&n);
ll x;
for(int i=1;i<=n;i++)
{
scanf("%lld",&x);
a[i]=zhuan(x);
}
ll ans=0;
even[0]=1;
for(int i=1;i<=n;i++)
{
sum[i]=sum[i-1]+a[i];
int mx=a[i];
for(int j=i-1;j>=max(i-128,1);j--)
{
mx=max(mx,(int)a[j]);
int ss=sum[i]-sum[j-1];
if(ss%2==0&&mx*2<=ss)
{
ans++;
}
}
if(i>129)
{
if(sum[i]&1)ans+=1ll*odd[i-130];
else ans+=1ll*even[i-130];
}
odd[i]=odd[i-1]+(sum[i]%2==1);
even[i]=even[i-1]+(sum[i]%2==0);
}
printf("%lld\n",ans);
return 0;
}