1. 程式人生 > 其它 >C - Moamen and XOR

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