ABC 365
Table of Contents
E - Xor Sigma Problem
https://atcoder.jp/contests/abc365/tasks/abc365_e
$\sum_{i,j} f(i,j)$ 系の問題は $i \leq j$ に関する $f(i,j)$ の値を表に書いてみて規則性を見つけると解けることが多い。
\begin{align} f(i,j) &= A_i \oplus A_{i+1} \oplus \cdots \oplus A_j \nonumber \\ S_i &= \sum_{j=i}^N f(i,j) \nonumber \end{align} と定義する。
表: $f(i,j)$ の値
| i\j | 1 | 2 | 3 | 
|---|---|---|---|
| 1 | 01 | 10 | 00 | 
| 2 | 11 | 01 | |
| 3 | 10 | 
\begin{align} \sum_{i=1}^{N-1} \sum_{j=i+1}^N f(i,j) &= \sum_{i=1}^{N} \left\{ \left( \sum_{j=i}^{N} f(i,j) \right) - f(i,i) \right\} \nonumber \\ &= \sum_{i=1}^{N} \left\{ \left( \sum_{j=i}^{N} f(i,j) \right) - A_i \right\} \nonumber \\ &= \sum_{i=1}^{N} S_i - A_i \nonumber \end{align}
\begin{align} dp_{i,k} &= \sum_{j=i}^N g(i,j,k) \nonumber \\ &\text{ where } g(i,j,k) = \begin{cases} 1 & \text{if } f(i,j) \text{ の } k \text{ bit 目が立っている} \\ 0 & \text{otherwise} \end{cases} \nonumber \end{align}
とすると
\begin{align} S_i = \sum_{k=0} dp_{i,k} \times 2^k \nonumber \end{align}
とかける。($dp_{i,k}$ は $f(i,j), (i \leq j)$ の $k$ bit 目が立っている個数)
また dp の遷移は
\begin{align} dp_{i+1,k} &= \begin{cases} N - i - dp_{i,k} & \text{if } A_i \text{ の } k \text{ bit 目が立っている} \\ dp_{i,k} & \text{otherwise} \end{cases} \nonumber \end{align}
となる。
※ $dp_{i+1,k}$ は $f(i+1,j), (i+1 \leq j)$ の $k$ bit 目が立っている個数を表しており、これは $A_i \oplus f(i,j)$ の $k$ bit 目が立っている個数のことである。($x \oplus x = 0$ よりこれは $A_i$ 分の寄与がなくなることと同義)
void solve() {
    int n;
    cin >> n;
    vll a(n);
    rep(i, n) cin >> a[i];
    vll ones(60, 0);
    ll xorsum = 0;
    ll sum = 0;
    for (ll x : a) {
        xorsum ^= x;
        sum += xorsum;
        rep(i, 60) {
            if ((xorsum >> i) & 1) {
                ones[i]++;
            }
        }
    }
    ll ans = 0;
    rep(i, n) {
        sum -= a[i];
        ans += sum;
        sum = 0;
        rep(j, 60) {
            if ((a[i] >> j) & 1) {
                ones[j] = n - i - 1 - (ones[j] - 1);
            }
            sum += (1ll << j) * ones[j];
        }
    }
    cout << ans << endl;
}