&安培;在C中是位AND。
示例:
m= 21(10101)
结果:
0 16 4 1 20 5 17 21
我的代码:
for(int i=0;i<=m;i++)
if ((i&m)==i) printf("%d ",i);
当m很大时,这将非常慢。
如何快速找到结果(答案很少,例如m = 2 ^ 30)?
答案 0 :(得分:4)
i = 0
repeat
print(i)
i = (i + (NOT m) + 1) AND m
until i == 0
UPD:
更简单的代码:
i = 0
repeat
print(i)
i = (i - 1) AND m
until i == 0
答案 1 :(得分:4)
接受的答案是正确的,但细节上有点稀疏,所以这里的为什么会起作用
观察集合{ n | n & m == n }
是所有n
的集合,以使n
中的位成为m
中的位的子集。如果所有这些位都在从最低有效位开始的组中,则可以通过简单地从0计数到m
来生成它们。
但是它们不一定分组,因此位之间可能有空格。应该跳过这些空格,如何通过递增跳过这些位?
那么你可以通过使它们成为1来进行传播(不完全跳过)传播。但是这些位留下了一些垃圾,必须将其清除掉。
因此,首先设置间隙中的位:i | ~m
(等效写为i ^ ~m
或i + ~m
,因为~m
中的位保证不与任何位重叠在i
)。
然后执行增量(+1
),然后扔掉空隙中留下的任何垃圾:& m
。
总计:((i | ~m) + 1) & m
。
对于新代码,观察通过间隙进行借位传播更容易,因为为了传播间隙,应该用零填充它已经存在的零。因此,唯一的问题是,间隙中可能会留下一些垃圾,应该使用& m
清除,总共(i - 1) & m
。
答案 2 :(得分:1)
一行代码:
for(i=m;i;i=(i-1)&m) printf("%d ",i);printf("0");