hihoCoder - 1526 Sequence Value

Description

给定一个长度为 \(n(n\le 10^5)\) 的序列 \(a[1..n]\),定义函数 \(f(b[1..m])\) 的值为在 \([0,m-1]\) 内满足如下条件的 \(i\) 的数目:

  • \(b\) 中前 \(i\) 个数异或起来的值小于 \(b\) 中前 \(i +1\) 个数异或起来的值。

对于 \(a[1..n]\) 的每个子序列 \(b[1..m]\) ,求 \(f(b[1..m])\) 之和。

Solution

我已经很久没有见到过这么水的样例了,告辞

\(dp[j][0/1]\) 表示前 \(i\) 个数有多少个子序列满足异或和在第 \(j\) 位为 \(0/1\) 。显然 \(x < x\oplus v\) 当且仅当 \(v\) 的二进制最高位在 \(x\) 对应位置上是 \(0\) 。然后就随便 \(dp\) 了。

我现在码风真棒

#include<bits/stdc++.h>
using namespace std;

template <class T> void read(T &x) {
    x = 0; bool flag = 0; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == 45) flag = 1;
    for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48; if (flag) x = -x;
}

#define N 100005
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
#define drp(i, a, b) for (int i = (a); i >= (b); i--)
#define P 998244353
#define ll long long

int a[N];
ll bin[N] = { 1 }, f[32][2];

inline void add(ll& x, int y) { (x += y) >= P ? x -= P : 0; }

int main() {
    int n; read(n);
    rep(i, 1, n) read(a[i]);
    rep(i, 1, n) bin[i] = (bin[i - 1] << 1) % P;
    rep(i, 0, 31) f[i][0] = 1;
    ll ans = 0;
    rep(i, 1, n) {
        drp(j, 31, 0) if (a[i] & (1 << j)) {
            add(ans, f[j][0] * bin[n - i] % P);
            break;
        }
        drp(j, 31, 0) {
            if (a[i] & (1 << j)) {
                int x = f[j][0], y = f[j][1];
                rep(t, 0, 1) f[j][t] = (x + y) % P;
            }
            else rep(t, 0, 1) add(f[j][t], f[j][t]);
        }
    }
    cout << ans;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/aziint/p/9463635.html