二进制枚举子集技巧

提供一个神奇的姿势

\(for(int \ i=sta;i;i=i-1\&sta)\)

稍微解释一下了,\(sta\)保存的0,1即为原来的需要求子集的集合,\(i\)即为遍历的子集

我们取的子集即是把当前集的元素取或不取,即\(sta\)的1取或不取

我们减去1,即是把最后一位的1变成0,最后一个1后面的0全变1,和原来的&一下,变的1全回去了,也把最后一位搞成0了

剩下的以此类推就差不多了

原文地址:https://www.cnblogs.com/ppprseter/p/9419344.html

时间: 2024-10-11 02:01:22

二进制枚举子集技巧的相关文章

1151 - Buy or Build(二进制枚举子集 + 并查集)

这题LRJ书上翻译的有问题,书上说两点之间的cost是两点的欧几里得距离,而题目要求两点的距离是两点欧几里得距离的平方. 其余就没什么好说的了,裸的并查集,需要注意的就是二进制枚举子集的问题. 二进制枚举子集: for(int i = 0 ; i < (1 << s) ; i++){ /*s是集合元素的个数*/ for(int j = 0 ; j < s ; j++){ if(!(s >> j) & 1) continue; else{ } } } 140548

【UVA】11464-Even Parity(二进制枚举子集)

枚举第一行的所有可能情况,之后根据上面行计算下面行(判断是否冲突),获得最终结果. 14058243 11464 Even Parity Accepted C++ 0.275 2014-08-18 05:14:15 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #include<stack> #inc

hdu 1557 权利指数 ( 二进制枚举子集) 解题心得

原题: Description 在选举问题中,总共有n个小团体,每个小团体拥有一定数量的选票数.如果其中m个小团体的票数和超过总票数的一半,则此组合为“获胜联盟”.n个团体可形成若干个获胜联盟.一个小团体要成为一个“关键加入者”的条件是:在其所在的获胜联盟中,如果缺少了这个小团体的加入,则此联盟不能成为获胜联盟.一个小团体的权利指数是指:一个小团体在所有获胜联盟中成为“关键加入者”的次数.请你计算每个小团体的权利指数. Input 输入数据的第一行为一个正整数T,表示有T组测试数据.每一组测试数

做实验 解题报告(二进制枚举子集)

题目描述 有一天,你实验室的老板给你布置的这样一个实验. 首先他拿出了两个长度为 n 的数列 a 和 b,其中每个 a i 以二进制表示一个集 合.例如数字 5 = (101) [2] 表示集合 {1, 3}.第 i 次实验会准备一个小盒子,里面装 着集合 a i 所有非空子集的纸条.老板要求你从中摸出一张纸条,如果满足你摸出的 纸条是 a i 的子集而不是 a i?b i ,a i?b i +1 ,...,a i?1 任意一个的子集,那么你就要被阿掉; 反之,你就逃过一劫. 令你和老板都没有想

(二进制枚举子集)买玩具

问题描述 蒜厂幼儿园有 n 个小朋友,每个小朋友都有自己想玩的玩具.身为幼儿园园长的你决定给幼儿园买一批玩具,由于经费有限,你只能买 m 个玩具.已知玩具商店一共卖 k 种玩具,编号为 1,2,3,…k,你让每个小朋友把想玩的玩具编号都写在了纸上.你希望满足尽可能多的小朋友的需求,请计算出最多同时能满足多少个小朋友的玩具需求. 输入格式 第一行,输入三个整数 n,m,k(1≤n≤100,1≤m≤k≤15),中间用空格分开. 接下来 n 行,第 i+1(0≤i< n) 行的第一个数字 ai代表第

二进制枚举子集

思路: 利用二进制的"开关"特性枚举: 具体为:假设给定集合A大小为n,则想象A = {a[0], a[1], ..., a[n-1]}的每个元素对应一个开关位(0或1),0表示不出现,1表示出现: 当每个元素的开关位的值确定时,就得到一个子集,因此共有2^n-1种情况(全0为空集,这里不考虑): 我们利用区间[1, 2^n-1],该区间上的每一个整数对应一个子集,对应方法是遍历该整数二进制表示的每一位: 若该位为1则相应子集中存在对应元素,否则不存在. 代码: #include &l

南阳OJ-91-阶乘之和---二进制枚举(入门)

题目链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=91 题目大意: 给你一个非负数整数n,判断n是不是一些数(这些数不允许重复使用,且为正数)的阶乘之和,如9=1!+2!+3!,如果是,则输出Yes,否则输出No:n<1000000; 思路: 数据量小,直接预处理出所有满足的数,然后直接判断就行了,预处理时用了二进制枚举子集的方式来处理 1 #include<iostream> 2 #include<cstdio>

子集的生成—二进制枚举

有这样的一个问题: 给定一个集合,让你输出所有的子集. 这时候二进制就派上了用场~ 我们用0,1来表示当前位是否被保留,值为1则保留,为0则舍弃 ,如下图所示: 那么对于一个有n个数的集合来讲,每一位有取和不取两种状态,一共就有2n种状态,我们可以从0一直枚举到2n来表示所有子集的状态. 但是现在问题又来了,对与我们枚举的数,你怎么知道哪一位是0,哪一位是1? 这个时候就要用到位运算的知识了,对于一个数S(子集的状态)我们拿它和0~n每一位i进行S&(1<<i)这样的运算就能得到对于的

UVa 818 切断圆环链(dfs+二进制枚举)

https://vjudge.net/problem/UVA-818 题意:有n个圆环,其中有一些已经扣在了一起.现在需要打开尽量少的圆环,使得所有圆环可以组成一条链,例如,有5个圆环,1-2,2-3,4-5,则需要打开一个圆环,如圆环4,然   后用它穿过圆环3和圆环5后再次闭合4,就可以形成一条链:1-2-3-4-5. 思路:从n个圆环中任意选择圆环,这就是枚举子集.所以这道题目可以用二进制枚举来做. 那么如何判断当前打开圆环是可行的呢?在去除打开的圆环后需要判断: ①:每个圆环的分支数都必