原题链接
考察:思维
思路:
从样例一很容易想到二进制1的个数一定要为偶数个,但是这样很容易想到反例:1 14,虽然总和也为偶数个但是不成立.这里就延伸出新的规则:1的个数最多的不超过总和的/2.
总结来说就是:\(sum[r]-sum[l-1]\)为偶,且\(maxn_{l,r}<=\frac{sum}{2}\).
先考虑优化求偶数区间和.我们用\(sum[i][0/1]\)记录1~i中,sum%2为1,0的个数.那么我们就可以\(O(n)\)算出只考虑前面条件的答案数.
\(manx<=64\),每个\(a_i\)至少贡献一个1,所以只需要考虑\((i-128,i]\)的最大值.
Code
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 300010;
int n,cnt[N],sum[N][2],s[N];
LL a[N],res;
LL lowbit(LL x)
{
return x&-x;
}
int get(LL x)
{
int sum = 0;
while(x)
{
sum++;
x -= lowbit(x);
}
return sum;
}
int main()
{
scanf("%d", &n);
sum[0][0] = 1;
for (int i = 1; i <= n;i++)
{
scanf("%lld", &a[i]);
cnt[i] = get(a[i]);
s[i] = s[i - 1] + cnt[i];
sum[i][s[i]%2]++;
sum[i][0] += sum[i - 1][0];
sum[i][1] += sum[i - 1][1];
res += sum[i - 1][s[i]%2];
}
for (int i = 1; i <= n;i++)
{
int l = max(i - 128, 0), maxn = 0;
for (int j = i - 1; j >= l;j--)
{
maxn = max(cnt[j+1], maxn);
if((s[j]-s[i])%2==0&&maxn>(s[i]-s[j])/2)
res--;
}
}
printf("%lld\n", res);
return 0;
}