目录
什么是二进制枚举子集
对于n个数,我们用n位二进制数来表示每个数的状态(选/不选),1代表选,0代表不选。
由数学知识可知,此时一共有2^n种情况,即 1 << n 种情况。
而这 2^n 种情况就对应着这 n 个数所选取组成的集合的数量。即n个数组成的集合的子集数量。
假设有5个数,那么5位二进制数为:xxxxx。
假设:11001,这就表示由第1、第4、第5个数组成的一个子集。
那么同样,对于一个长度为n的数组,想要求它的所有子集,就可以从 0 遍历到 2^n - 1,其中每个数由二进制表示,就对应该数组中的部分元素。
那么如何判定 nums数组中的某一个数 是否在列举出来的某一个子集里面呢?
假设当前列举出来的子集为:41 = 0101001。
可以看出来,第1、4、6个数在该子集中,那么如何通过计算进行判断呢?
判断第4个数在其中:
对于 位运算: 1 << 3 = 0001000,此时 (0101001) & (0001000) ≠ 0 ,此时就代表第4个数在该子集中。
即:假设当前子集的二进制表示对应十进制数 number,判断第 x 个数是否在当前子集中,就用 number & ( 1 << (x-1) ),若结果不为0,则第x个数存在于该子集中。
注意,这里第x数,如果从1开始数,那么后面就是 1 << (x-1)。如果从0开始数,就是 1 << x。具体问题具体分析。
接下来是一些例题。
得到整数X
描述
小明有 n个互不相同的正整数,现在他要从这 n个正整数之中无重复地选取任意个数,并仅通过加法凑出整数 X。求小明有多少种不同的方案来凑出整数 X。
输入
第一行,输入两个整数 n,X(1≤n≤20,1≤X≤2000)。
接下来输入 n个整数,每个整数不超过 100。输出
输出一个整数,表示能凑出X的方案数。
用例输入:
6 6
1 2 3 4 5 6
用例输出: