Так что это всего лишь предварительный набросок алгоритма. Это работает, когда верхняя граница сама по себе является числом Фибоначчи, но я не уверен, как адаптировать его для общих верхних границ. Надеюсь, кто-то может улучшить это.
Общая идея состоит в том, чтобы взглянуть на структуру кодировок Фибоначчи. Вот первые несколько цифр:
0
1
10
100
101
1000
1001
1010
10000
10001
10010
10100
10101
100000
Инвариант в каждом из этих чисел состоит в том, что никогда не бывает пары последовательных единиц. Учитывая этот инвариант, мы можем увеличивать от одного числа к следующему, используя следующий шаблон:
- Если последняя цифра равна 0, установите ее на 1.
- Если последняя цифра равна 1, то поскольку последовательных цифр 1 нет, установите последнюю цифру на 0, а следующую цифру на 1.
- Устраните любые удвоенные 1 с, установив их оба на 0 и установив следующую цифру на 1, повторяя, пока все удвоенные 1 не будут устранены.
Причина того, что это важно, в том, что свойство (3) говорит нам кое-что о структуре этих чисел. Давайте еще раз рассмотрим первые несколько чисел в кодировке Фибоначчи. Посмотрите, например, на первые три числа:
00
01
10
Теперь посмотрите на все четырехбитные числа:
1000
1001
1010
Следующий номер будет иметь пять цифр, как показано здесь:
1011 & rarr; 1100 & rarr; 10000
Интересно отметить, что число с четырьмя цифрами равно числу значений с двумя цифрами. Фактически, мы получаем четырехзначные числа, просто добавляя префикс самое большее двухзначное число к 10.
Теперь посмотрите на трехзначные числа:
000
001
010
100
101
И посмотрите на пятизначные числа:
10000
10001
10010
10100
10101
Обратите внимание, что пятизначные числа - это просто трехзначные числа с префиксом 10.
Это дает нам очень интересный способ подсчитать, сколько 1s. В частности, если вы посмотрите на (k + 2) -значные числа, каждое из них является просто k-значным числом с префиксом 10. Это означает, что если во всех k-значных числах имеется общее количество B 1, то общее количество B в числах, состоящих из k + 2 цифр, равно B плюс количество k-значных чисел, поскольку мы просто воспроизведение последовательности с дополнительным 1, добавленным к каждому номеру.
Мы можем использовать это для вычисления числа 1 в кодировках Фибоначчи, которые имеют не более k цифр в них. Хитрость заключается в следующем - если для каждого количества цифр мы отслеживаем
- Сколько чисел имеет самое большее столько цифр (назовите это N (d)), и
- Сколько единиц представляют числа с не более чем d цифрами (назовите это B (d)).
Мы можем использовать эту информацию для вычисления этих двух частей информации для еще одной цифры. Это прекрасное повторение DP. Первоначально, мы посеем это следующим образом. Для одной цифры N (d) = 2 и B (d) равно 1, поскольку для одной цифры числа 0 и 1. Для двух цифр N (d) = 3 (есть только одно двузначное число, 10, и два однозначных числа 0 и 1) и B (d) равно 2 (одно из 1, одно из 10). Оттуда у нас есть
- N (d + 2) = N (d) + N (d + 1). Это связано с тем, что число чисел, содержащее до d + 2 цифр, представляет собой число чисел, содержащее до d + 1 цифр (N (d + 1)), плюс числа, образованные путем добавления префикса 10 к числам с d цифрами (N ( г)) * * тысячу пятьдесят-один
- B (d + 2) = B (d + 1) + B (d) + N (d) (общее количество 1 бит в количестве не более d + 2 равно общему количеству 1 бит в числа длиной не более d + 1, плюс дополнительные, которые мы получаем из чисел, состоящих всего из d + 2 цифр)
Например, мы получаем следующее:
d N(d) B(d)
---------------------
1 2 1
2 3 2
3 5 5
4 8 10
5 13 20
Мы действительно можем это проверить. Для однозначных чисел используется всего один бит. Для двузначных чисел есть два (1 и 10). Для трехзначных чисел существует пять единиц (1, 10, 100, 101). Для четырехзначных чисел существует 10 (пять предыдущих, плюс 1000, 1001, 1010). Расширение этого внешнего вида дает нам последовательность, которую мы хотели бы.
Это очень легко вычислить - мы можем вычислить значение для k цифр за время O (k) с использованием только O (1) памяти, если мы будем использовать пространство ранее. Поскольку числа Фибоначчи экспоненциально быстро растут, это означает, что если у нас есть какое-то число N и мы хотим найти сумму всех битов 1 с наибольшим числом Фибоначчи, меньшим, чем N, мы можем сделать это во времени O (log N) и пространстве O (1). * +1061 *
Тем не менее, я не уверен, как адаптировать это для работы с общими верхними границами. Тем не менее, я настроен оптимистично, что есть какой-то способ сделать это. Это прекрасное повторение, и просто должен быть хороший способ его обобщить.
Надеюсь, это поможет! Спасибо за потрясающую проблему!