Идея этого ответа может помочь вам разработать очень быстрое решение. Имея диапазоны 0..2 ^ N, сложность потенциального алгоритма в худшем случае будет равна O (N) (при условии, что сложность длинной арифметики равна O (1)). При правильном программировании он должен легко обработать N = 1000000 в дело миллисекунд.
Представьте, что у нас есть следующие значения:
LO = 0; (0000000000000000000000000000000)
HI = 2147483647; (1111111111111111111111111111111)
Наименьшее возможное значение N1 в диапазоне LO..HI равно 0
Максимально возможное значение N1 в диапазоне LO..HI составляет 31
.
Таким образом, вычисление части N2..NN выполняется только для одного из 32 значений (т. Е. 0..31).
Что можно сделать просто, даже без компьютера.
Теперь давайте вычислим величину N1 = X для диапазона значений LO..HI
Когда у нас есть X = 0, мы имеем счет (N1 = X) = 1, это следующее значение:
1 0000000000000000000000000000000
Когда у нас есть X = 1, мы имеем количество (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
Edit:
F(N, M) = Binomial(N + M, M)
Теперь давайте рассмотрим пример из реальной жизни:
LO = 43797207; (0000010100111000100101011010111)
HI = 1562866180; (1011101001001110111001000000100)
Итак, как нам применить нашу уникальную формулу перестановок к этому примеру? Так как мы не знаем как
«1» находится ниже LO, а «1» - выше HI.
Итак, давайте посчитаем эти перестановки ниже 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)!
Edit:
f(U, M) = 1 + Binomial(U - 1 + M, M)
Теперь вернемся к нашему примеру из реальной жизни:
LO = 43797207; (0000010100111000100101011010111)
HI = 1562866180; (1011101001001110111001000000100)
Итак, мы хотим посчитать количество циклов, необходимое для выполнения следующего
преобразования (предположим, 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 «потерянных» циклов, которые расположены ниже 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
Я не предоставлю оставшуюся часть решения. Это не так сложно понять оставшуюся часть. Удачи!