これ、てんぷら君のおかげで随分とシンプルな問題になった!
問題概要
個の 0 以上の整数 が与えられる。各 に対して、
- xor xor xor としたときの
- xor xor xor の値を求めよ。
制約
解法
XOR に関する問題は各桁ごとに考えるのは常套手段ではある。つまり、各桁 に対して、次のように考える。
の中に 桁目が 1 になっているものの個数を としたとき、次のようになる。
- が奇数ならば の 桁目は 1
- が偶数ならば の 桁目は 0
これを踏まえて、 xor xor xor のうち、 桁目が 1 となっているものの個数 は次のように求められる。
- が奇数のときは の 桁目が 0-1 反転するので、
- が偶数のときは、
このようにして求めた に対して、 を合計していけば答えが求められる。
差分更新へ
上記の作業を に対して順に実施していく必要がある。しかし、 の値は、差分だけ見て更新することが可能である。
よって、全体の計算量は、 を最大の桁数として で抑えられる。
#include <iostream> #include <vector> using namespace std; int main() { int N; cin >> N; vector<long long> a(N); for (int i = 0; i < N; ++i) cin >> a[i]; const int DIGIT = 35; vector<int> ones(DIGIT, 0); for (int k = 0; k < N; ++k) { long long res = 0; for (int d = 0; d < DIGIT; ++d) { if (a[k] & (1LL<<d)) ++ones[d]; res += (1LL<<d) * (ones[d] % 2 == 0 ? ones[d] : k+1 - ones[d]); } printf("%lld\n", res); } }