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;
}
posted @ 2018-08-12 17:16  aziint  阅读(97)  评论(0编辑  收藏  举报
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.