我想要一个N位数的下一个+100,000值,因为结果值也必须有N位。
例如:30是0b11110
下一个值是39 × 1 m1n1x;
我读了that links,得到了一个用N位找到下一个值的方法。
现在,有没有一种方法可以一次“跳”10万个值?
10万在这里是任意的,它可以是-更高。
我能想到的唯一方法是从我的初始值进行跳跃,计算新值的位数,并在位级别将新值调整为我想要的N位。这是一个非常手动的过程,我想知道是否存在更有效的算法。但它不能保证跳变的值的数量。
我想要一个N位数的下一个+100,000值,因为结果值也必须有N位。
例如:30是0b11110
下一个值是39 × 1 m1n1x;
我读了that links,得到了一个用N位找到下一个值的方法。
现在,有没有一种方法可以一次“跳”10万个值?
10万在这里是任意的,它可以是-更高。
我能想到的唯一方法是从我的初始值进行跳跃,计算新值的位数,并在位级别将新值调整为我想要的N位。这是一个非常手动的过程,我想知道是否存在更有效的算法。但它不能保证跳变的值的数量。
2条答案
按热度按时间epfja78i1#
下面是Maxim 1000的回答:
如果
C(n,k)
是设置了k位的n位值的数量,则C
就是binomial coefficient。它可以计算为C(n,k) = C(n-1,k-1) * n / k
,极限为C(n,0) = C(n,n) = 1
(和0 <= k <= n
)。从那里,您可以通过从最高有效位到最低有效位(从左到右)迭代数字的位来计算数字的索引。如果数字总共有n位,并且设置了k位,那么当遇到位设置时,索引是
C(bit_position, k) + subindex
,其中bit_position
是位的位置(0是最低有效位,n-1是最高有效位),如果您取消设置该位,则subindex
是数字的索引。请注意,如果两个数字设置了不同数量的位,则它们可以具有相同的索引。例如,有10个5位数,其中设置了3位。以下是它们,沿着它们的索引:
10110
的索引为6:--第一个比特集位于位置4,其中设置了3个比特,因此是
C(4,3)
;C(2,2)
;--第三位设置在位置1,剩下1位设置,因此
C(1,1)
。这就是
C(4,3) + C(2,2) + C(1,1) = 4 + 1 + 1 = 6
。要从索引转到相应的数字,您只需要执行相反的操作:从值0开始,设置对应于
C(p,k)
的每个位,其中k
是已知常数,p
从n-1
到0
。然后,要向前跳转
j
值,您可以转换为数字的索引,将j
添加到它,并转换回数字。下面是一个实现:
它可能可以进一步优化,但希望这是写得足够清楚,给予你的想法。
下面是一个使用
std::next_permutation
的简单实现,以测试优化的实现:您可以在this complete demo中尝试这两种方法。
czfnxgou2#
我们可以尝试按照数值的顺序索引所有具有N 1的值。之后,我们可以计算起始数字的索引,将100000添加到它,然后将索引再次转换为数字。
我们称
f(M,N)
为具有N个1的M位值的数量(它是N!/M!/(N-M)!
)。如果我们的数字在最高有效位中为0,我们可以将其视为(M-1)位值。如果它的MSB是1,我们可以计算100...00
之前的N位数(即f(M-1,N)
),并将100...00
之后的N位数(即(N-1)1的(M-1)位数)相加。这允许我们将N1的数字转换为它的索引。如果我没有错过任何东西,转换回来只是逆转每一步。
复杂度看起来像
O(max-bit-count)
。PS.听起来很复杂,希望有人能找到更简单的...