【数学】【位运算】Divan and bitwise operations—CF1614C

Divan and bitwise operations—CF1614C
参考文章

思路

假设 a a a 数组有 k k k 个数的二进制第 i i i 位上的数字是 1 1 1,那么 a a a 数组中二进制第 i i i 位对答案的贡献为:
w = 2 i − 1 ∗ ( C k 1 + C k 3 + C k 5 + . . . + C k 比 k 小的最大奇数 ) ∗ C k n − k w=2^{i-1}*(C_k^1+C_k^3+C_k^5+...+C_k^{比k小的最大奇数})*C_k^{n-k} w=2i1(Ck1+Ck3+Ck5+...+Ckk小的最大奇数)Cknk
其中, 2 i − 1 2^{i-1} 2i1 表示二进制第 i i i 位的权重; ( C k 1 + C k 3 + C k 5 + . . . + C k 比 k 小的最大奇数 ) (C_k^1+C_k^3+C_k^5+...+C_k^{比k小的最大奇数}) (Ck1+Ck3+Ck5+...+Ckk小的最大奇数) 表示在 k k k 个有序的 1 1 1 排列中,有多少种选法能选出奇数个 1 1 1 C k n − k C_k^{n-k} Cknk 表示在 n − k n-k nk 个有序的 0 0 0 排列中,有多少种选法。
因为
( C k 1 + C k 3 + C k 5 + . . . + C k 比 k 小的最大奇数 ) = 2 k − 1 (C_k^1+C_k^3+C_k^5+...+C_k^{比k小的最大奇数}) = 2^{k-1} (Ck1+Ck3+Ck5+...+Ckk小的最大奇数)=2k1
所以
w = 2 i − 1 ∗ 2 n − 1 w = 2^{i-1}*2^{n-1} w=2i12n1
我们可以看出: a a a 中如果存在数在它的二进制第 i i i 位是 1 1 1,那么第 i i i 位的整体贡献就是定值 2 i − 1 ∗ 2 n − 1 2^{i-1}*2^{n-1} 2i12n1,与 1 1 1 的个数无关。

所以我们现在的任务就变成了寻找一个数 y y y,使得 x x x 中二进制每一位都是 a a a 数组中二进制每一位的按位或,即 y = a 1 , a 2 , a 3 , . . . a n 的按位或 y = a_1, a_2, a_3, ... a_n 的按位或 y=a1,a2,a3,...an的按位或,这很容易做到,让 y y y 与所有的 x x x 按位或即可。

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 = 2e5 + 10;
const int mod = 1e9 +7;

int n, m;

int qpow(int a, int b) {
	int res = 1;
	while (b) {
		if (b & 1) {
			res = res * a % mod;
		}
		a = a * a % mod;
		b >>= 1;
	}
	return res;
}

void solve() {
	cin >> n >> m;
	
	int y = 0;
	while (m --) {
		int l, r, x;
		cin >> l >> r >> x;
		y |= x;
	}
	
	cout << "          ";
	cout << y * qpow(2, n - 1) % mod << "\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++)