会员
周边
众包
新闻
博问
闪存
赞助商
所有博客
当前博客
我的博客
我的园子
账号设置
简洁模式
...
退出登录
注册
登录
Lemon-GPU
摸一天鱼,划一天水;坚决不努力,能偷懒就偷懒
博客园
首页
新随笔
联系
订阅
管理
给定一个二进制表达的数,如何快速获得他的子集
这种题目说白了,就是这样的: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
)
编辑
收藏
举报
会员力量,点亮园子希望
刷新页面
返回顶部
公告