给定一个二进制表达的数,如何快速获得他的子集

  • 这种题目说白了,就是这样的:010110,求他的所有子集。这种题目通常会出现在哪里呢?题目首先给定一个集合,然后你用二进制的方法求他的所有子集,然后你还需要在某个子集的补集里面继续求子集。比如蓝桥杯ALGO-1004:无聊的逗。
  • 我们从010110(亦即十进制的22)开始,求他的子集。网上的一种方法就是这样的:int set = 22; for(int i = set; i > 0; i = (i - 1) & set);。这种方法自然很好,但是似乎没有给出一个比较直觉的证明——又或许是我没看到。所以,我们在这里给出一个十分不严谨的直觉。
  • 整个方法的关键就是在于i = (i - 1) & set,所以问题就在于这到底是怎么完成的。我们可以这么想:原来的集合减去1后,字母序最小的1会被替换为0,比字母序最小的1还要字母序意义上小的0会被变为1——这也叫借位,之后,我们又使用“与”计算,把这个字母序最小的1去除,只剩下下一个集合。那你也许会问了:010110 -> 010100 -> 010010,这个010010怎么来的。我们之前说了,比字母序最小的1还要字母序意义上小的0会被变为1,所以,这个更后面的1会被留下来。
  • 当然这只是一个十分不严谨的证明,严谨的证明还望读者们不吝赐教了。
posted @ 2022-01-27 19:28  Lemon-GPU  阅读(86)  评论(0编辑  收藏  举报