这个答案的思路可以帮助您开发非常快的解决方案。具有范围0..2^N的情况下,潜在算法的复杂度将在最坏情况下为O(N)(假设长算数的复杂度为O(1))。如果正确编程,它应该可以在毫秒内轻松处理N = 1000000。
想象一下我们有以下的值:
LO = 0; (0000000000000000000000000000000)
HI = 2147483647; (1111111111111111111111111111111)
在范围LO..HI中,最小的N1为0,最大的N1为31。
因此,N2..NN部分的计算仅针对32个值之一(即0..31)进行,这可以简单地完成,甚至不需要计算机。现在让我们计算一下当X在范围LO..HI内取多少值时N1=X的数量。
当X=0时,我们有count(N1=X)=1,这是以下值:
1 0000000000000000000000000000000
当我们有X = 1时,我们有count(N1=X) = 31,这些是以下值:
01 1000000000000000000000000000000
02 0100000000000000000000000000000
03 0010000000000000000000000000000
...
30 0000000000000000000000000000010
31 0000000000000000000000000000001
当X=2时,我们有以下模式:
1100000000000000000000000000000
有29个数字'0'和2个数字'1',可以组成多少个不同的字符串?
假设最右边的数字'1'(#1)从左到右循环,我们得到以下图像:
01 1100000000000000000000000000000
02 1010000000000000000000000000000
03 1001000000000000000000000000000
...
30 1000000000000000000000000000001
现在我们有30个独特的字符串,当将“1”(#1)从左边移动到右边时,无法通过任何方向移动“1”(#1)来创建一个独特的字符串。这意味着我们应该将“1”(#2)移到右边,同时尽可能将“1”(#1)的位置重置为左侧,以保持独特性,我们得到:
01 0110000000000000000000000000000
现在我们再次对“1”(#1)进行一次循环
02 0101000000000000000000000000000
03 0100100000000000000000000000000
...
29 0100000000000000000000000000001
现在我们有29个独特的字符串,如果我们继续这个操作28次,我们就会得到以下表达式。
count(N1=2) = 30 + 29 + 28 + ... + 1 = 465
当X=3时,图像保持类似,但我们移动的是'1'(#1)、'1'(#2)和'1'(#3)
移动'1'(#1)会创建29个独特字符串,当我们开始移动'1'(#2)时,我们得到
29 + 28 + ... + 1 = 435个独特字符串,之后我们需要处理的是'1'(#3),因此我们有
29 + 28 + ... + 1 = 435
28 + ... + 1 = 406
...
+ 1 = 1
435 + 406 + 378 + 351 + 325 + 300 + 276 +
253 + 231 + 210 + 190 + 171 + 153 + 136 +
120 + 105 + 091 + 078 + 066 + 055 + 045 +
036 + 028 + 021 + 015 + 010 + 006 + 003 + 001 = 4495
让我们尝试解决一般情况,即当我们有N个零和M个一时。
长度为(N + M)的字符串的总排列数量等于(N + M)!
这个字符串中“0”的重复量等于N!
这个字符串中“1”的重复量等于M!
因此,由N个零和M个一组成的唯一字符串的总数为
(N + M)! 32! 263130836933693530167218012160000000
F(N, M) = ============= => ========== = ====================================== = 4495
(N!) * (M!) 3! * 29! 6 * 304888344611713860501504000000
编辑:
F(N, M) = Binomial(N + M, M)
现在让我们考虑一个现实生活中的例子:
LO = 43797207
HI = 1562866180
那么如何将我们独特的排列组合公式应用于这个例子呢?因为我们不知道在 LO 下面有多少个 '1',在 HI 上面有多少个 '1'。
所以让我们计算 LO 下面和 HI 上面的这些排列。
让我们记住如何循环 '1'(#1), '1'(#2)...
1111100000000000000000000000000 => 2080374784
1111010000000000000000000000000 => 2046820352
1111001000000000000000000000000 => 2030043136
1111000000000000000000000000001 => 2013265921
1110110000000000000000000000000 => 1979711488
1110101000000000000000000000000 => 1962934272
1110100100000000000000000000000 => 1954545664
1110100010000000000000000000001 => 1950351361
正如您所见,此循环过程平稳地降低十进制值。因此,我们需要计算到达HI值的循环次数。但是我们不应该按一计算这些值,因为最坏情况下可以生成高达32!/(16!*16!) = 601080390个循环,我们将非常长时间地进行循环 :)
因此,我们需要一次循环块中的“1”循环。
以我们的示例为例,我们希望计算变换的循环次数。
1111100000000000000000000000000 => 1011101000000000000000000000000
1011101001001110111001000000100
那么,需要多少个周期才能引起变化?
1111100000000000000000000000000 => 1011101000000000000000000000000
让我们看看这个变换:
1111100000000000000000000000000 => 1110110000000000000000000000000
等于以下循环集合:
01 1111100000000000000000000000000
02 1111010000000000000000000000000
...
27 1111000000000000000000000000001
28 1110110000000000000000000000000
所以我们需要28个周期来转换。
1111100000000000000000000000000 => 1110110000000000000000000000000
我们需要多少个周期来进行转换?
1111100000000000000000000000000 => 1101110000000000000000000000000
执行以下步骤,我们需要:
1110110000000000000000000000000 28 cycles
1110011000000000000000000000000 27 cycles
1110001100000000000000000000000 26 cycles
...
1110000000000000000000000000011 1 cycle
并且需要1个周期来接收:
1101110000000000000000000000000 1 cycle
因此,收到的是28 + 27 + ... + 1 + 1 = 406 + 1的值。
但我们之前已经看到过这个值,它是计算2个“1”和27个“0”时唯一排列数量的结果。这意味着在移动时循环的次数。
11100000000000000000000000000 => 01110000000000000000000000000
等同于移动
_1100000000000000000000000000 => _0000000000000000000000000011
再加上一个额外的周期
这意味着,如果我们有M个零和N个一,并且想要将U中的“1”块向右移动,我们需要执行以下数量的周期:
(U - 1 + M)!
1 + =============== = f(U, M)
M! * (U - 1)!
编辑:
f(U, M) = 1 + Binomial(U - 1 + M, M)
现在让我们回到我们的现实生活例子:
LO = 43797207
HI = 1562866180
我们想要做的是计算执行以下转换所需的周期数(假设N1 = 6)
1111110000000000000000000000000 => 1011101001000000000000000000000
1011101001001110111001000000100
这相当于:
1011101001000000000000000000000 1011101001000000000000000000000
------------------------------- -------------------------------
_111110000000000000000000000000 => _011111000000000000000000000000 f(5, 25) = 118756
_____11000000000000000000000000 => _____01100000000000000000000000 f(2, 24) = 301
_______100000000000000000000000 => _______010000000000000000000000 f(1, 23) = 24
________10000000000000000000000 => ________01000000000000000000000 f(1, 22) = 23
因此,导致了119104个“丢失”的周期,这些周期位于HI以上。
关于LO,无论我们以何种方向进行循环,实际上并没有区别,因此为了计算LO,我们可以进行反向循环:
0000010100111000100101011010111 0000010100111000100101011010111
0000000000000000000000000111___ => 0000000000000000000000001110___ f(3, 25) = 2926
00000000000000000000000011_____ => 00000000000000000000000110_____ f(2, 24) = 301
因此,导致了3227个“lost”周期位于LO以下。
overall amount of lost cycles = 119104 + 3227 = 122331
overall amount of all possible cycles = F(6, 25) = 736281
N1 in range 43797207..1562866180 is equal to 736281 - 122331 = 613950
我不会提供解决方案的其余部分。理解剩下的部分并不那么难。祝你好运!