CF1557C Moamen and XOR

C. Moamen and XOR
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
input
3
3 1
2 1
4 0
output
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].

题意:
给定一个整数n和一个整数k,要求构造一个长度为n的数组,每个元素小于 2k的数字使得这些数字进行与运算后不小于这些数字进行异或或运算,这样的数组有多少种,对1e9+7取模。
思路:
将每个数字每一位单独看。首先知道一个异或的性质,对于某一位上,该位上有奇数个1异或该位运算结果为1,该位上有偶数个1异或该位上运算结果为0。对比与的性质,对于某一位上,该位上全为1与运算结果为1,否则该位上运算结果为0。根据如上对比大概就知道要分n为奇数个和偶数个讨论。

1.n为奇数时
考虑与运算大于异或运算的情况,对于任意一位要使该位与运算大于异或运算,也就是使与运算结果为1,异或运算结果为0,那么所有的数字该位都为1,并且该位有偶数个数字为1,因为n为奇数,所以矛盾了,那么n为奇数的时候不存在任意一位的与运算大于异或运算。该情况下符合条件的情况数为0.
考虑与运算结果等于异或运算的情况,也就是对于任意一位该位上的与运算结果=该位上的异或结果。先看一下同时为1的情况,也就是所有数字该位上都为1。再看一下同时为0的情况,该位上选择偶数个数字该位为1就可以了。综上两个方面所述,也就是n个数字里面选偶数个数字该位为1或者n个数字里面选择全部数字该位为1,则该位满足条件,每个数字有k位,所以该讨论情况下的方案总数为:
[ C(n,0)+C(n,2)+C(n,4)+…+C(n,n-1)+C(n,n) ] k (k次方是因为一共有k位,每一位都要符合条件)
C(n,0)+C(n,2)+C(n,4)+…+C(n,n-1)=2n-1
所以 [ C(n,0)+C(n,2)+C(n,4)+…+C(n,n-1)+C(n,n) ] k=(2n-1+1)k

所以n为奇数时的方案总数为(2n-1+1)k

2.n为偶数时
考虑与运算结果等于异或运算的情况。先看一下某一位上与运算结果与异或运算结果同时为1是否可行,因为n为偶数个,与运算为1的时候异或运算一定为0,这样的情况下与运算比异或运算大,所以这种情况我们当前讨论下不要。某一位上与运算结果和异或运算结果均为0时,也就是该位上有偶数个数字为1但是不能所有数字该位都为1,也就是n个数字里面选出偶数个数字但是不能选出全部数字该位都为1,这一位的选择方案数就是 [ C(n,0)+C(n,2)+C(n,4)+…+C(n,n-2) ]= 2n-1-1。因为有k位,所以n为偶数时与运算和异或运算结果相同的情况有(2n-1-1) k种。

考虑与运算结果大于异或运算结果的情况,枚举i位 (0≤i<k,含义为2i)与运算大于异或运算的情况,这种情况下小于该位的位上面1的个数可以任取,也就是每一位都可以**[C(n,0)+C(n,1)+C(n,2)+…+C(n,n)]=2n 种情况,大于该位的均为与运算等于异或运算的情况上面已经求得也就是[ C(n,0)+C(n,2)+C(n,4)+…+C(n,n-2) ]=2n-1-1**,大于该位的不取C(n,n)是因为取了之后枚举所有i会重复取。有i个小于i为的位,有k-i-1个大于i位的位,所以对于i位有(2n)i × ( 2n-1-1 )k-i-1种,遍历i从0到k-1就得到了这种情况下的方案总数。

所以得到n为偶数的情况下方案总数为 (2n-1-1) k +(2n)i × ( 2n-1-1 )k-i-1

代码实现如下

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll qp(ll x,ll p)//快速幂
{
	ll ans=1;
	x%=mod;
	while(p)
	{
		if(p&1)
		{
			ans*=x;
			ans%=mod;
		}
		x*=x;
		x%=mod;
		p>>=1;
	}
	return ans;
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		ll n,k;
		scanf("%lld%lld",&n,&k);
		ll ans;
		if(n%2==1)//n为奇数的情况,方案数为(2^(n-1)+1)^k
		{
			ans=qp(qp(2,n-1)+1,k);
		}
		else//n为偶数的情况
		{
			ans=qp(qp(2,n-1)-1,k);//n为偶数情况下与运算和异或运算结果相同的方案数(2^(n-1)-1)^k
			ans%=mod;
			/*
			n为偶数情况下i位与运算大于异或运算的方案数为[(2^n)^i]*[(2^(n-1)-1)^(k-1-i)]
			*/
			for(int i=0;i<k;i++)
			{
				ans+=((qp(qp(2,n),i)%mod)*(qp(qp(2,n-1)-1,(k-1-i))%mod))%mod;
				ans%=mod;
			}
		}
		
		ans%=mod;
		printf("%lld\n",ans);
	}
	
return 0;
} 
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值