タイトル
質問の意味:
でバイナリ1の任意の位置に変更することができる配列要素のセットを与えられました。決定された区間[L、R]、その結果ゼロの排他的OR演算値後の素子間隔。出力セクションのような数。
分析:
この最初の問題については、通常、右のセクションのカウントに行く、その後、左側のセクションを列挙。
以来ビット数は限り我々はそれに数1の各カウントを考慮するとして、任意に配置することができます。総数が1より大きく、最大1の二倍総数に適格である偶数である。のためのセクション、私たちは常にマイナス2の合計数の大半を排除1 1を使用することができますので、最大のマイナス1は、二度の状態のままです。でも、自然は、1にXORと、明らかです。
63で最大で1の数の数、2倍以上のように、合計範囲ため、第1の条件は必ずしも満たさ。限り、我々は偶数個の1を維持するようすることができます。現在の間隔[I、J]のノートでは、我々は、ゲージを移動このセクション番号の[j + 1、k]は、数1であり、元のセクションでは、1の偶数、すなわち[J + 1まで追加します、n]は、この範囲内で[J + 1、k]は、奇数または偶数の数です。
1つの数が添加されているので、我々は最初の接頭辞及びvを計算することができる[I]は、で表される[1、I]はセクション1の数、及びその後の接尾辞とCNTを維持[I]は[I、n]はこの間隔のVを表しますj]はカウントするために偶数です。だから我々は間隔の数の[J、K]をカウントすると、接頭辞を減算することによって得ることができる。とき 我々は唯一のそのパリティに焦点を当てているので、V [j]が偶数の場合、そう、何の効果は、パリティの数を入れ替えることができません。
#include <iostream>
using namespace std;
typedef long long ll;
int num[300005],v[300005],cnt[300005];
int count(ll x)
{
int ans = 0;
while( x )
{
if( x & 1 ) ans ++;
x >>= 1;
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
ll x;
cin >> x;
num[i] = count(x);
}
for (int i = 1; i <= n; i++)
{
v[i] = v[i-1] + num[i];
}
for (int i = n; i >= 1; i--)
{
cnt[i] = cnt[i+1];
if( v[i] % 2 == 0 ) cnt[i] ++;
}
ll ans = 0;
for (int i = 1; i <= n; i++)
{
int sum = num[i];
int maxn = num[i];
for (int j = i + 1; j <= n; j++)
{
sum += num[j];
maxn = max(maxn,num[j]);
if( sum % 2 == 0 && 2*maxn <= sum ) ans ++;
if( sum > 128 )
{
if( sum % 2 == 0 )
{
if( v[j] % 2 == 0 ) ans += cnt[j+1];
else ans += n - j - cnt[j+1];
}else
{
if( v[j] % 2 == 0 ) ans += n - j - cnt[j+1];
else ans += cnt[j+1];
}
break;
}
}
}
cout << ans << '\n';
return 0;
}