【组合数学专练】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].
我们先一位一位的看:
- 当前位上,若有至少一个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\)
- 当前位上,若每个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;
}