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;
}