【组合数学专练】CF1557C (1700)

### Moamen and XOR

C. Moamen and XOR
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Moamen and Ezzat are playing a game. They create an array a of n non-negative integers where every element is less than 2k.

Moamen wins if a1&a2&a3&…&an≥a1⊕a2⊕a3⊕…⊕an.

Here & denotes the bitwise AND operation, and ⊕ denotes the bitwise XOR operation.

Please calculate the number of winning for Moamen arrays a.

As the result may be very large, print the value modulo 1000000007 (109+7).

Input
The first line contains a single integer t (1≤t≤5)— the number of test cases.

Each test case consists of one line containing two integers n and k (1≤n≤2⋅105, 0≤k≤2⋅105).

Output
For each test case, print a single value — the number of different arrays that Moamen wins with.

Print the result modulo 1000000007 (109+7).

Example
inputCopy
3
3 1
2 1
4 0
outputCopy
5
2
1
Note
In the first example, n=3, k=1. As a result, all the possible arrays are [0,0,0], [0,0,1], [0,1,0], [1,0,0], [1,1,0], [0,1,1], [1,0,1], and [1,1,1].

Moamen wins in only 5 of them: [0,0,0], [1,1,0], [0,1,1], [1,0,1], and [1,1,1].

我们先一位一位的看:

  1. 当前位上,若有至少一个ai的二进制位是0,要想&的值大于等于^的值,则 二进制位上1的个数必须是偶数。
  • n为奇数时 \(sum = \sum_{2 \mid i}^{n-1} C_{n}^{i}\)
  • n为偶数时候\(sum = \sum_{2 \mid i}^{n-2} C_{n}^{i}\)
    一共有k位 所以 \(res = sum^k\)
  1. 当前位上,若每个ai的二进制位都是1
  • n为奇数时,只有每一位全1 &才等于^的结果
    最终结果 \(res+1\)
  • n为偶数时候,当前位全1 则&大于^的结果,所以只需当前位之前有偶数个1,之后随便取
    最终结果 \(sum = \sum_{i=1}^{k}sum^{i-1}2^{n*(m-i)}\)
    这题阶乘求逆元要整着算
const int N = 2e5 + 10;
const int M = 2e5 + 5;
ll F[N],inv[N];
ll qmi(ll  m,ll k){
    ll res=1;
    while(k){
        if(k&1)res=res*m%mod;
        m=m*m%mod;
        k>>=1;
    }
    return res%mod;
}
ll C(ll a,ll b){
    return F[a]%mod*inv[a-b]%mod*inv[b]%mod;
}
void solve(){
    ll n,k;
    cin>>n>>k;
    ll ans = 0;
    if(n&1){
        ll sum = 1;
        for(int i = 0; i <= n; i += 2 ){
            sum += C(n,i);
            sum%=mod;
        }
        ans = qmi(sum,k);
    }
    else{
        ll sum = 0;
        for(int i = 0; i <= n-2; i += 2 ){
            sum += C(n,i);
            sum%=mod;
        }

        ans = qmi(sum,k);
        for(int i=1;i<=k;i++){
            ans=(ans+qmi(sum,i-1)*qmi(2,n*(k-i)))%mod;
        }
    }
    cout<<ans<<endl;
}
void init(int n){
   F[0]=inv[0]=1;
    for(int i=1;i<n;i++){
        F[i]=F[i-1]*i%mod;
        inv[i]=inv[i-1]*qmi(i,mod-2)%mod;
    }
}
int main(){
    int t;
    cin>>t;
    init(M);
    while(t--){
        solve();
    }
    return 0;
}
posted @ 2021-09-11 10:12  qingyanng  阅读(40)  评论(0编辑  收藏  举报