本文主要是介绍【数学】【位运算】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=2i−1∗(Ck1+Ck3+Ck5+...+Ck比k小的最大奇数)∗Ckn−k。
其中, 2 i − 1 2^{i-1} 2i−1 表示二进制第 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+...+Ck比k小的最大奇数) 表示在 k k k 个有序的 1 1 1 排列中,有多少种选法能选出奇数个 1 1 1; C k n − k C_k^{n-k} Ckn−k 表示在 n − k n-k n−k 个有序的 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+...+Ck比k小的最大奇数)=2k−1
所以
w = 2 i − 1 ∗ 2 n − 1 w = 2^{i-1}*2^{n-1} w=2i−1∗2n−1
我们可以看出: a a a 中如果存在数在它的二进制第 i i i 位是 1 1 1,那么第 i i i 位的整体贡献就是定值 2 i − 1 ∗ 2 n − 1 2^{i-1}*2^{n-1} 2i−1∗2n−1,与 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 <bits/stdc++.h>
#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;
}
这篇关于【数学】【位运算】Divan and bitwise operations—CF1614C的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!