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