链接 : C. Moamen and XOR
题意 : 给定 \(n\) 个数和 \(k\), 保证每个数 \(a_i\lt 2^k\), 问使得 \(a_1 \ \&\ a_2\ \&\ a_3\ \&\ ...\ \&\ a_n \ge a_1 \oplus a_2 \oplus a_3 \oplus ...a_n\) 的数组个数.
思路 :
每个数不小于 \(2^k\) 即有 \(k\) 位.
若 \(n\) 为奇数 :
从 \(a_1 \ \&\ a_2\ \&\ a_3\ \&\ ...\ \&\ a_n\) 与 \(a_1 \oplus a_2 \oplus a_3 \oplus ...a_n\) 得到的数的最高位看起, 假设当前第 \(i\) 位, 如果该位 \(\&\) 操作得到的是 \(1\), 那么 \(\oplus\) 操作得到的也必然是 \(1\), 这里只有 \(1\) 种情况. 如果该位 \(\&\) 操作得到的是 \(0\), 为了保证条件, 必须也让 \(\oplus\) 操作得到的也是 \(0\). 有 \(\sum C_n^{j}=2^{n-1}\) 种情况 (这里必须保证 \(j\) 为偶数且不等于 \(n\)). 依次枚举每一位, 每一位互相没有干扰, 因此答案 \(ans=(2^{n-1}+1)^k\).
若 \(n\) 为偶数 :
从 \(a_1 \ \&\ a_2\ \&\ a_3\ \&\ ...\ \&\ a_n\) 与 \(a_1 \oplus a_2 \oplus a_3 \oplus ...a_n\) 得到的数的最高位看起, 假设当前第 \(i\) 位, 如果该位 \(\&\) 操作得到的是 \(1\), 那么 \(\oplus\) 操作得到必然为 \(0\), 于是在该位之后, 所有 \(a\) 的 \([i-1,1]\)位都可任取, 有 \(2^{(i-1)n}\) 种情况. 如果该位 \(\&\) 操作得到的是 \(0\), 为了保证条件, 必须也让 \(\oplus\) 操作得到的也是 \(0\). 有 \(\sum C_n^{j}=2^{n-1}-1\) 种情况 (这里必须保证 \(j\) 为偶数且不等于 \(n\)). 我们假设 \(t=2^{n-1}-1\), 再去看第 \(i-1\) 位. 同样有上述情况划分, 于是答案 :
\[ans=2^{(k-1)n}+t*(2^{(k-2)n}+t*(2^{(k-3)n}+t*(...)) \]特别的, 若 \(n=1\), \(ans = 2^k\).
代码 :
#include <bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);
inline int lowbit(int x) { return x & (-x); }
#define ll long long
#define ull unsigned long long
#define pb push_back
#define PII pair<int, int>
#define VIT vector<int>
#define x first
#define y second
#define inf 0x3f3f3f3f
const int mod = 1e9 + 7;
ll qmi(ll a, ll k) {
ll res = 1;
while (k) {
if (k & 1) res = res * a % mod;
a = a * a % mod;
k >>= 1;
}
return res;
}
int main() {
//freopen("in.txt", "r", stdin);
IO;
int T;
cin >> T;
while (T--) {
ll n, k;
cin >> n >> k;
if (k == 0) {
cout << "1\n";
continue;
}
if (n == 1) {
ll ans = qmi(2, k);
cout << ans << '\n';
continue;
}
ll ans = 0;
if (n & 1) {
ans = qmi(2, n - 1) + 1;
ans = qmi(ans, k);
} else {
ll t = qmi(2, n - 1) - 1, last = 1;
for (int i = k; i > 0; --i) {
ans = (ans + (last * qmi(2, (i - 1) * n) % mod) % mod);
last = last * t % mod;
}
ans = (ans + last) % mod;
}
cout << ans << '\n';
}
return 0;
}