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+...+Cnn−1=2n−1(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=2n−1(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+Cn1xn−1+...+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+...+Cnn−1=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+...+Cnn−1=2n−1 -
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+...+Cnn−1=2n−1种,因为我们现在讨论的是这 n n n个数里面一位二进制位的情况,一共有 k k k位,所以总的情况数是 ( 2 n − 1 + 1 ) k (2^{n-1}+1)^k (2n−1+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=2n−1−1,同样这是一个位置,一共有 k k k个位置,所以相等情况总数为 ( 2 n − 1 − 1 ) k (2^{n-1}-1)^k (2n−1−1)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 i−1个位置和后面的 k − i k-i k−i个位置,那么现在满足最优子结构性质和无后效性,考虑当前位置的时候是建立在前面都相等的情况之下且对后面没有影响,所以现在对于这一位来说是一种情况,他前面的 i − 1 i-1 i−1个位置有多少情况呢?显然每个位置都应该是一个 0 = 0 0=0 0=0的状态,也就是这 n n n个数的该位置有偶数(不包括零)个 1 1 1,这其实和上面那个讨论是一样的,一共有 ( 2 n − 1 − 1 ) i − 1 (2^{n-1}-1)^{i-1} (2n−1−1)i−1种情况;那么 i i i位置后面的 k − i k-i k−i个位置无所谓了,一共有 ( 2 n ) k − i (2^n)^{k-i} (2n)k−i种情况,这样根据分类加法和分步乘法计数原理,总的方案数是 ( 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 (2n−1−1)i−1×(2n)k−i+(2n−1−1)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} {(2n−1+1)k∑i=1k(2n−1−1)i−1×(2n)k−i+(2n−1−1)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;
}
- 写的感觉很细了,应该没有含混不清的措辞