【位运算】Sum of XOR Functions—CF1879D

Sum of XOR Functions—CF1879D
参考文章

这个题真的很难,比我以前写过的1700分的题都难。

由于这个是edu场的题,网上的题解很少,找个好长时间,最后找到一个比较好理解的题解。

思路

这道题用了“拆位法”。jls几乎没思考就写出来了,但我都没有听说过这个方法,还是写的题太少了。

题目中涉及到位运算,不难发现,不同的二进制位之间对答案的贡献是互不影响的。所以我们就可以考虑使用拆位法。

如此,对于 n n n 个元素二进制中的第 k k k 位,把它们按顺序组成一个 01 01 01 字符串, a a a 数组二进制第 k k k 位的总贡献就是 now_res,其中 now_res = “所有包含奇数个 1 1 1 的区间”的区间长度之和。

易知:一个区间可以看作是两个前缀相减的结果,因此,如果我们要求的区间 [ l ,   r ] [l,~r] [l, r] 需要满足有奇数个 1 1 1,那么需要满足: [ 1 ,   l ] [1,~l] [1, l] 有偶数个 1 1 1 [ 1 ,   r ] [1,~r] [1, r] 有奇数个 1 1 1,或者是满足 [ 1 ,   l ] [1,~l] [1, l] 有奇数个 1 1 1 [ l ,   r ] [l,~r] [l, r] 有偶数个 1 1 1

【位运算】Sum of XOR Functions—CF1879D_第1张图片


C o d e Code Code

#include 
#define int long long
#define sz(a) ((int)a.size())
#define all(a) a.begin(), a.end()
using namespace std;
using PII = pair<int, int>;
using i128 = __int128;
const int N = 3e5 + 10;
const int mod = 998244353;

int n;
int a[N];

void solve() {
	cin >> n;
	for (int i = 1; i <= n; i ++) {
		cin >> a[i];
	}
	
	int res = 0;
	for (int k = 0; k <= 30; k ++) { // 因为不同位互相独立,所以可以分别计算每一位的贡献
		int num[2] = {1, 0}, sum[2] = {0, 0};
		int parity = 0;
		int now_res = 0;
		for (int i = 1; i <= n; i ++) {
			parity = (parity + (a[i] >> k & 1)) % 2;
			now_res = (now_res + num[1 - parity] * i - sum[1 - parity]) % mod;
			num[parity] ++;
			sum[parity] += i;
		}
		res = (res + now_res * (1 << k) % mod) % mod;
	}
	
	cout << "         ";
	cout << res << "\n";
}

signed main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int T = 1;
//	cin >> T; cin.get();
	while (T --) solve();
	return 0;
}

你可能感兴趣的:(位运算,c++,算法)