Codeforces Round #737 (Div. 2) 1557. C. Moamen and XOR(组合数,位)

博客探讨了一种动态规划的方法来解决一个位运算计数问题。具体任务是构造一个长度为n的数组,使得数组元素在[0,2^k-1]范围内,并满足位与和位异或相等的条件。文章详细分析了两种情况:位与大于位异或和位与等于位异或,并给出了对应的解决方案。通过递推公式和二进制位的处理,计算了不同情况下方案数的模运算结果。
摘要由CSDN通过智能技术生成

LINK

题意

构造一个长 n n n的数组 a a a,使得 a i ∈ [ 0 , 2 k − 1 ] a_i\in[0,2^k-1] ai[0,2k1]

且满足 a 1 & a 2 & a 3 . . . & a n = a 1 ⊕ a 2 ⊕ a 3 . . . ⊕ a n a_1\&a_2\&a_3...\&a_n=a_1\oplus a_2 \oplus a_3...\oplus a_n a1&a2&a3...&an=a1a2a3...an

求方案数


考虑从二进制高位依次考虑到低位

在之前的位与值和异或值相等,这部分方案是 p r e pre pre,现在考虑在第 i i i位与值更大

Ⅰ.在这一位,数组的与已经大于数组的异或

那么必定数组与起来是 1 1 1,而异或起来是 0 0 0

也就是所有 a i a_i ai在这一位都必须取 1 1 1,此时 n n n 1 1 1异或

n n n为偶数,显然可行,那么后面的 k − i k-i ki位二进制怎么取都无所谓,每个数都有 2 k − i 2^{k-i} 2ki取法

所以答案加上 p r e ∗ ( 2 k − i ) n pre*(2^{k-i})^n pre(2ki)n

n n n为奇数,不可行,奇数个 1 1 1异或起来还是 1 1 1,还是相等

Ⅱ.在这一位,数组的与等于数组的异或

考虑当数组与为 1 1 1,异或也为 1 1 1,显然只有当 n n n取奇数,这一位二进制全取 1 1 1有一种解法

考虑当数组与为 0 0 0,异或也为 0 0 0,也就是选择偶数个位置这一位填充 1 1 1,其余位置填充 0 0 0

方案数为 ∑ i % 2 = = 0 ( n i ) = 2 n − 1 \sum\limits_{i\%2==0}\binom{n}{i}=2^{n-1} i%2==0(in)=2n1(这个可以用二项式定理推导)

所以 n n n为奇数时, p r e + = 2 n − 1 + 1 pre+=2^{n-1}+1 pre+=2n1+1,因为此时 n n n个数可以全为 1 1 1,所以多了一种方案

n n n为偶数时, p r e + = 2 n − 1 − 1 pre+=2^{n-1}-1 pre+=2n11,因为此时 n n n个数不能全为 1 1 1,所以少了一种方案

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 3e5+10;
const int mod = 1e9+7;
int t,n,k,inv[maxn];
int quick(int x,int n)
{
	int ans = 1;
	for( ; n ; n>>=1,x=x*x%mod )
		if( n&1 )	ans = ans*x%mod;
	return ans;
}
void upd(int &x,int y){ x = (x+y)%mod; }
signed main()
{
	inv[0] = 1;
	for(int i=1;i<=200000;i++) 	inv[i] = inv[i-1]*2%mod;
	cin >> t;
	while( t-- )
	{
		cin >> n >> k;
		int ans = 0,pre = 1;
		for(int i=1;i<=k;i++)
		{
			if( n%2==0 )
			{ 
				upd( ans,pre*quick( inv[k-i],n )%mod );
				pre = pre*( inv[n-1]-1 )%mod;
			}
			else
				pre = pre*( inv[n-1]+1 )%mod;
		}
		upd( ans,pre );
		cout << ( ans%mod+mod )%mod << endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值