Codeforces Round #737 (Div. 2) C. Moamen and XOR

https://codeforces.com/problemset/problem/1557/C
给出n和k,让你构造一个 n n n个非负整数构成的数组,其中所有整数不超过 2 k 2^k 2k,满足所有元素的与和 ≥ \geq 异或和,问能构造多少个这样的数组

  • 首先证明两个等式
    C n 0 + C n 2 + C n 4 + . . . + C n n − 1 = 2 n − 1 ( n 为 奇 数 ) 1 ◯ C_n^0+C_n^2+C_n^4+...+C_n^{n-1}=2^{n-1}(n为奇数)\text{\textcircled 1} Cn0+Cn2+Cn4+...+Cnn1=2n1(n)1 C n 0 + C n 2 + C n 4 + . . . + C n n = 2 n − 1 ( n 为 偶 数 ) 2 ◯ C_n^0+C_n^2+C_n^4+...+C_n^n=2^{n-1}(n为偶数)\text{\textcircled2} Cn0+Cn2+Cn4+...+Cnn=2n1(n)2
    我们知道 ( 1 + x ) n = C n 0 x n + C n 1 x n − 1 + . . . + C n n (1+x)^{n}=C_n^0x^n+C_n^1x^{n-1}+...+C_n^n (1+x)n=Cn0xn+Cn1xn1+...+Cnn,当 n n n为奇数时,令 x = − 1 x=-1 x=1,可得 C n 0 + C n 2 + C n 4 + . . . + C n n − 1 = C n 1 + C n 3 + . . . + C n n C_n^0+C_n^2+C_n^4+...+C_n^{n-1}= C_n^1+C_n^3+...+C_n^{n} Cn0+Cn2+Cn4+...+Cnn1=Cn1+Cn3+...+Cnn ∵ C n 0 + C n 1 + . . . + C n n = 2 n \because C_n^0+C_n^1+...+C_n^n=2^n Cn0+Cn1+...+Cnn=2n ∴ C n 0 + C n 2 + C n 4 + . . . + C n n − 1 = 2 n − 1 \therefore C_n^0+C_n^2+C_n^4+...+C_n^{n-1}=2^{n-1} Cn0+Cn2+Cn4+...+Cnn1=2n1

  • 1 ◯ \text{\textcircled 1} 1式得证,同理可得 2 ◯ \text{\textcircled 2} 2

  • 知道了这两条等式以后,再来看这道题,考虑一下,什么时候与和会大于异或和呢?如果 n n n是奇数有可能吗?因为按位与见 0 0 0就是 0 0 0,所以只有一个机会那就是那个二进制位所有的数都是1,在这种情况下,异或和也是 1 1 1,所以这二者只能相等,可以很自然的引出奇数和偶数这二者的分类讨论

  • 如果 n n n是奇数,因为与和和异或和只能相等,那么上面说过了为 1 1 1的情况只有一种;那么如果为 0 0 0呢?因为与和只要有一个 0 0 0结果就是 0 0 0,重点在于异或这边, n n n为奇数,必然是偶数个 1 1 1+奇数个 0 0 0,所以情况一共有 C n 0 + C n 2 + C n 4 + . . . + C n n − 1 = 2 n − 1 C_n^0+C_n^2+C_n^4+...+C_n^{n-1}=2^{n-1} Cn0+Cn2+Cn4+...+Cnn1=2n1种,因为我们现在讨论的是这 n n n个数里面一位二进制位的情况,一共有 k k k位,所以总的情况数是 ( 2 n − 1 + 1 ) k (2^{n-1}+1)^k (2n1+1)k

  • 如果 n n n是偶数,假设二者相等,如果等于 1 1 1,那么所有数都得是 1 1 1,结果发现不可能,如果等于0,那么 1 1 1出现次数是 2 , 4 , 6 , . . . , n 2,4,6,...,n 2,4,6,...,n,结果是 C n 2 + C n 4 + . . . + C n n = 2 n − 1 − 1 C_n^2+C_n^4+...+C_n^n=2^{n-1}-1 Cn2+Cn4+...+Cnn=2n11,同样这是一个位置,一共有 k k k个位置,所以相等情况总数为 ( 2 n − 1 − 1 ) k (2^{n-1}-1)^k (2n11)k
    如果不相等,左面是 1 1 1,右面是 0 0 0,也就是这 n n n个数的这一个二进制位全是 1 1 1,注意我们一直讨论的都是二进制的一个位置,一共有 k k k个位置,这里其实是一个 d p dp dp的思路,可以把这 k k k个位置分成当前位置 i i i,前面的 i − 1 i-1 i1个位置和后面的 k − i k-i ki个位置,那么现在满足最优子结构性质和无后效性,考虑当前位置的时候是建立在前面都相等的情况之下且对后面没有影响,所以现在对于这一位来说是一种情况,他前面的 i − 1 i-1 i1个位置有多少情况呢?显然每个位置都应该是一个 0 = 0 0=0 0=0的状态,也就是这 n n n个数的该位置有偶数(不包括零)个 1 1 1,这其实和上面那个讨论是一样的,一共有 ( 2 n − 1 − 1 ) i − 1 (2^{n-1}-1)^{i-1} (2n11)i1种情况;那么 i i i位置后面的 k − i k-i ki个位置无所谓了,一共有 ( 2 n ) k − i (2^n)^{k-i} (2n)ki种情况,这样根据分类加法和分步乘法计数原理,总的方案数是 ( 2 n − 1 − 1 ) i − 1 × ( 2 n ) k − i + ( 2 n − 1 − 1 ) k (2^{n-1}-1)^{i-1}\times (2^n)^{k-i}+(2^{n-1}-1)^k (2n11)i1×(2n)ki+(2n11)k
    这是 i i i位置确定之后的方案总数

  • 综上所述,奇数和偶数的方案如下
    { ( 2 n − 1 + 1 ) k n是奇数 ∑ i = 1 k ( 2 n − 1 − 1 ) i − 1 × ( 2 n ) k − i + ( 2 n − 1 − 1 ) k n是偶数 \begin{cases} (2^{n-1}+1)^k&\text{n是奇数}\\ \sum_{i=1}^k(2^{n-1}-1)^{i-1}\times (2^n)^{k-i}+(2^{n-1}-1)^k&\text{n是偶数} \end{cases} {(2n1+1)ki=1k(2n11)i1×(2n)ki+(2n11)kn是奇数n是偶数

  • 编程解决

#include <iostream>
using namespace std;
typedef long long ll;
const ll MOD = 1e9 + 7;
const int MAXN = 2e5 + 100;
ll fastpow(ll base, ll power){
	ll ans = 1;
	while(power){
		if(power & 1) ans = ans * base % MOD;
		base = base * base % MOD;
		power >>= 1;
	}
	return ans;
}
int main(){
	ios::sync_with_stdio(false);
	int t;
	ll n, k;
	cin >> t;
	while(t--){
		cin >> n >> k;
		ll a = fastpow(2, n - 1);
		ll ans;
		if(n & 1){
			ans = fastpow(a + 1, k);
		}else{
			ans = fastpow(a - 1, k);
			for(int i=1;i<=k;i++){
				ans += fastpow(a - 1, i - 1) * fastpow(2 * a, k - i) % MOD;
				ans %= MOD;
			}
		}
		cout << ans << '\n';
	}
	return 0;
}

  • 写的感觉很细了,应该没有含混不清的措辞
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clarence Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值