『容斥·状压』CF449D Jzzhu and Numbers
P r o b l e m \mathrm{Problem} Problem
给出一个长度为n的序列 a 1 , a 2 . . . a n a_1,a_2...a_n a1,a2...an。
求构造出一个序列 i 1 ≤ i 2 ≤ . . . ≤ i k ( 1 ≤ k ≤ n ) i_1 \le i_2 \le ... \le i_k(1\le{k}\le{n}) i1≤i2≤...≤ik(1≤k≤n)使得 a i 1 a n d a i 2 a n d . . . a n d a i k = 0 a_{i_1}\mathrm{\ and\ }a_{i_2}\mathrm{\ and\ }...\mathrm{\ and}\ a_{i_k}=0 ai1 and ai2 and ... and aik=0
求方案数模 1 0 9 + 7 10^9+7 109+7 。
也就是从 { a i } \{a_i\} {ai} 里面选出一个非空子集使这些数按位与起来为 0 0 0.
S o l u t i o n \mathrm{Solution} Solution
前置芝士: 求 n n n个数中,任意 i i i 有几个数满足 a i a n d i = i a_i\ \mathrm{and\ } i=i ai and i=i。
考虑状压: f i ∑ j ∉ i f i + 2 j f_i\sum _{j∉i}f_{i+2^j} fij∈/i∑fi+2j
这样我们发现会有重复,考虑为什么会重复。
那么怎么办呢?首先想到的容斥,即:加上新增 1 1 1 的,减去新增 2 2 2 的…
但是我们神奇的发现将 i i i 和 j j j 的枚举顺序调换一下,就神奇的不重复了。
因此我们得到了一个做状压计数的结论:
- 若某一个数想要求得以它为子集的数的所有贡献,我们只需要调换枚举顺序,累计每一次新增 1 1 1 的贡献即可。
回到正题,那么这题运用上述结论就十分好解决了。
我们设 f i f_i fi 表示and值为 i i i 的答案,我们发现十分难搞。但是令 f i f_i fi表示and值子集为 i i i 的方案数,我们发现我们可以用 f i f_i fi 减去以 i i i 的贡献即为正确答案。
类比上面的前置芝士,我们发现我们只要将加号改成减号就可以得到答案。
那么我们才能得到 f i f_i fi 呢,我们发现只要有 n n n 个数的子集存在 i i i,答案即为: 2 n − 1 2^n-1 2n−1
因此我们先令上述统计个数一遍,在变换成方案数以后再相减一遍即可。
C o d e \mathrm{Code} Code
#include <bits/stdc++.h>
#define int long longusing namespace std;
const int N = 3e6;
const int P = 1e9 + 7;int n, S;
int f[N];int read(void)
{int s = 0, w = 0; char c = getchar();while (!isdigit(c)) w |= c == '-', c = getchar();while (isdigit(c)) s = s*10+c-48, c = getchar();return w ? -s : s;
}int power(int a, int b) {int res = 1;while (b > 0) {if (b & 1) res = res * a % P;a = a * a % P, b >>= 1;}return res;
}void DP(int x)
{for (int j=0;j<=19;++j){for (int i=S-1;i>=0;--i)if (((i >> j) & 1) == 0) f[i] = (f[i] + f[i | 1 << j] * x) % P;}return;
}signed main(void)
{n = read(), S = (1 << 20) - 1;for (int i=1;i<=n;++i) f[read()] ++;DP(1);for (int i=0;i<=S;++i) f[i] = power(2, f[i]) - 1;DP(-1); cout << (f[0] + P) % P << endl;return 0;
}
『容斥·状压』CF449D Jzzhu and Numbers相关推荐
- [容斥 状压DP] HDU4997. Biconnected
令 fSf_S 表示点集 SS 的答案,gSg_S 表示点集 SS 的连通图个数 那么 gSg_S 可以通过枚举与编号最小的点联通的点集求出来 fS=gS−∑T∈SgT×MT,S−Tf_S=g_S-\ ...
- [容斥 状压DP 树形DP] BZOJ 4455 [Zjoi2016]小星星 UOJ #185 【ZJOI2016】小星星
杜老师说的哦 据说有人n*3^n卡过去 ? UOJ上需要卡常哦 #include<cstdio> #include<cstdlib> #include<algorithm ...
- cf449D. Jzzhu and Numbers(容斥原理 高维前缀和)
题意 题目链接 给出\(n\)个数,问任意选几个数,它们\(\&\)起来等于\(0\)的方案数 Sol 正解居然是容斥原理Orz,然而本蒟蒻完全想不到.. 考虑每一种方案 答案=任意一种方案 ...
- [CQOI2012] 局部极小值(状压DP + 容斥 + 搜索)
problem luogu-P3160 solution 这么小的数据范围,非暴力不状压.暴力 O(28!)O(28!)O(28!) 呵呵呵可以拉走了. 我们不妨从小到大填数字,这样如果局部极小值点还 ...
- P3160:局部极小值(容斥、状压)
解析 又是一道我不会的容斥题 qwq 本题的一个关键性质:答案有解时,极小值不超过8个 所以可以对其进行状压 考虑从小到大填数 那么在极小值填完之前,它的八连通必然是不能填的 设计dpi,sdp_{i ...
- Wannafly挑战赛19:C. 多彩的树(状压+容斥)
链接:https://www.nowcoder.com/acm/contest/131/C 来源:牛客网 题目描述 有一棵树包含 N 个节点,节点编号从 1 到 N.节点总共有 K 种颜色,颜色编号从 ...
- BZOJ 2560: 串珠子 (状压DP+枚举子集补集+容斥)
(Noip提高组及以下),有意者请联系Lydsy2012@163.com,仅限教师及家长用户. 2560: 串珠子 Time Limit: 10 Sec Memory Limit: 128 MB Su ...
- 20200515省选模拟赛B、幻化成风(毒瘤容斥题+构造容斥系数+生成函数+hash状压DP+Trie树优化背包)
题解 花了一上午+一中午终于把这道题A了 首先,我们要求的是bi互不相同的合法方案数 我们可以枚举一个a的集合S,来强制里面的b全部都相同,然后其它的随便放 由于这个题的n的约数非常多,我们可以把它质 ...
- Codeforces Round #257 (Div. 1) D. Jzzhu and Numbers 高维前缀和 + 容斥
传送门 文章目录 题意: 思路: 题意: 思路: 完全想不到容斥啊,看了半天也没看懂渍渍渍. 定义f[i]f[i]f[i]表示iii的超集个数,那么选择的方案就是2f[i]−12^{f[i]}-12f ...
最新文章
- android 过度绘制
- C语言的补码表示和unsigned及signed的转换
- 通过webbrowser实现js与winform的相互调用
- Pytest高级进阶之Fixture
- linux 分割pdf,PDFBox分割PDF文档
- CF962E Byteland, Berland and Disputed Cities
- nodejs创建http服务器
- 迅捷pdf转换器(文件格式转换器)
- Windows 10 让所有程序默认为“以管理员身份运行”并且取消“确认”按钮
- 美国交通信号配时实践经验
- ipad协议更新非常稳定
- 【网站】八大极品桌面壁纸网站,惊艳
- LOL英雄联盟打不了文字,打字就一闪一闪的,英文可以,解决方式
- 好系统帮你恢复win7经典开机画面
- 断点续传续播的大概原理
- AutoMapper Project To OrderBy Skip Take 正确写法
- 04 分布式文件系统以及MapReduce入门程序
- 《PHASEN:A Phase and Harmonics-Aware Speech Enhancement Network》Pytorch代码学习
- php 多个一维数组合拼成二维数组的方法
- MICCAI 论文投稿须知翻译