C - Moamen and XOR

链接 : 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;
}
posted @ 2021-08-10 18:54  phr2000  阅读(94)  评论(0编辑  收藏  举报