赞
踩
题目链接:C.Moamen and XOR
题目大意:
一个含有n个数的数组,每个数都要满足小于2的k次方,求满足a1 &a2&a3&…&an≥a1⊕a2⊕a3⊕…⊕an.的个数
思路:
k<=2e5,再加上题中的位运算符号,很自然的想到用二进制来表示数组中的每一个数以及最终的结果,我们一位一位分析,设前一个式子为A,后一个式子为B,则可画出以下表格
| A的第k位 | B的第k位 | |
|---|---|---|
| 1 | n个数的第k位全为1 | n个数的第k位一共含有奇数个1 |
| 0 | n个数的第k位不全为1 | n个数的第k位一共含有偶数个1 |
显然我们要分奇偶讨论,并且从低位向高位枚举,当枚举到某一位时,他的高位全部设为0,并设ans[i]表示0~i位一共有多少种满足题意的情况
当n为偶数时:
当
A
的
第
k
位
为
1
,
B
的
第
k
位
为
0
时
,
此
时
n
个
数
的
第
k
位
有
1
种
情
况
,
n
个
数
的
0
到
k
−
1
位
有
2
(
n
∗
(
k
−
1
)
)
种
情
况
当A的第k位为1,B的第k位为0时,此时n个数的\\第k位有1种情况,n个数的0到k-1位有2^{(n*(k-1))}种情况
当A的第k位为1,B的第k位为0时,此时n个数的第k位有1种情况,n个数的0到k−1位有2(n∗(k−1))种情况
即
ans[i] = (ans[i] + quick_pow(2,n*(i-1),mod)) % mod;
当A的第k位为1,B的第k位为0时,n一定是奇数,不符合大条件。
当A的第k位为0,B的第k位为0时,此时n个数的第M位有1种情况,
(
M
=
C
n
0
+
C
n
2
+
…
…
+
C
n
(
n
−
2
)
=
2
(
n
−
1
)
−
1
)
(M=C_n^0+C_n^2+……+C_n^{(n-2)}=2^{(n-1)}-1)
(M=Cn0+Cn2+……+Cn(n−2)=2(n−1)−1)
,0~k-1位有ans[i-1]种情况即
ans[i] = (ans[i] + (ans[i - 1]) * (quick_pow(2,n-1,mod)-1)) % mod;
当n为奇数时:
当A的第k位为1,B的第k位为0时,n一定是偶数,不符合大条件。
当A的第k位为0,B的第k位为1时,不满足题意。
当A的第k位为1,B的第k位为1时,此时n个数的第k位有1种情况,0~k-1位有ans[i-1]种情况,即
ans[i] = (ans[i] + ans[i - 1]) % mod。
当A的第k位为0,B的第k位为0时,此时n个数的第M位有1种情况,
M
=
C
n
0
+
C
n
2
+
…
…
+
C
n
(
n
−
1
)
=
2
(
n
−
1
)
M=C_n^0+C_n^2+……+C_n^{(n-1)}=2^{(n-1)}
M=Cn0+Cn2+……+Cn(n−1)=2(n−1)
即
ans[i] = (ans[i] + (ans[i - 1]) * (quick_pow(2,n-1,mod)% mod)) % mod;
code:
#include <bits/stdc++.h> #define DEBUG freopen("_in.txt", "r", stdin); // #define DEBUG freopen("_in.txt", "r", stdin), freopen("_out.txt", "w", stdout); typedef long long ll; typedef unsigned long long ull; using namespace std; const ll maxn = 3e5 + 10; const ll maxm = maxn * 2; const ll INF = 0x3f3f3f3f3f3f3f3f; const double pi = 3.1415926; const ll mod = 1e9 + 7; ll res[maxn], ans[maxn]; ll quick_pow(ll a,ll b,ll MOD) { ll ans=1,base=a; while(b!=0) { if(b&1) ans=ans%MOD*base%MOD; base=base%MOD*base%MOD; b>>=1; } return ans%MOD; } int main() { // DEBUG; ll T; scanf("%lld", &T); while (T--) { ll n, k; memset(res, 0, sizeof(res)); memset(ans, 0, sizeof(ans)); scanf("%lld%lld", &n, &k); ans[0]=1; for (ll i = 1; i <= k; i++) { if (n % 2 == 0) { ans[i] = (ans[i] + quick_pow(2,n*(i-1),mod)) % mod; ans[i] = (ans[i] + (ans[i - 1]) * (quick_pow(2,n-1,mod)-1)) % mod; } else { ans[i] = (ans[i] + ans[i - 1]) % mod; ans[i] = (ans[i] + (ans[i - 1]) * (quick_pow(2,n-1,mod)% mod)) % mod; } } printf("%lld\n",ans[k]); } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。