А у меня другой ответ:
. Рекуррентное соотношение имеет вид
Все как и у Вас. Рассматриваем n-битные числа. Если старший бит 0, то для таких чисел сумма единиц равна
. Далее имеем две группы чисел.
1. Числа начинаются на 11. Для них старшая единица не является одинокой, поэтому вклад дает только младшая. А это все числа вида 11xxxxxxx01,11xxxxxxx010, 11xxxxxxx0100 ... . Таких, очевидно,
2. Числа начинаются на 10. Для них старшая единица всегда одинокая. Ее вклад равен
. Какой вклад дает младшая единица?. Это все числа вида 10xxxxxxx01,10xxxxxxx010, 10xxxxxxx0100 ... Таких, как мы видели,
. Плюс еще одно число 10100...0. Итого, таких
. А сумма единиц равна
Суммируем и получаем рекуррентное соотношение.
С исходной задачей аналогично. Нам понадобится вспомогательная задача.
Задано число Z. Найти количество всех чисел не превосходящих Z, у которых есть одинокая
правая единица. Пусть эта задача решена. Соответствующую функцию назовем G(Z).
Переходим к исходной задаче. Задано n-битное число Z. Два варианта.
1. Число Z начинается на 10. Тогда все не превосходящие его числа либо начинаются на 0 (и для них сумма единиц известна и равна
) либо начинаются на 10. Для таких чисел левая единица одинокая и ее вклад в общую сумму равен просто количеству таких чисел
. А сумма правых одиноких единиц совпадает с
, где
- это число образованное младшими
разрядами числа Z. Отдельно надо еще разобраться с числом 10100...0.
2. Число Z начинается на 11. Как и раньше легко получаем
(начинаются на 0) плюс
(начинаются на 10) плюс
.
Таким образом, надо просто уметь решать вспомогательную задачу нахождения
.
Эта вспомогательная задача решается за линейное время относительно количества бит n.
Ну действительно. Всякое нужное нам число X имеет вид
и оно должно быть не больше числа
(
- соответствуют 01 в числе X)
Отсюда видим, что если
- это 01, 10, 11, то необходимо и достаточно, чтобы
, а для
равного 00, необходимо и достаточно, чтобы
Итак, количество таких чисел либо
либо
. Количество этих экстра-единиц легко подсчитывается.
Далее, что же это за числа
. Да это же сдвиги вправо исходного числа Z. Записав сумму этих чисел в столбик, видим, что сумма битов в каждом разряде (столбике) отличается от предыдущей суммы одним лишь битом числа Z. Ну например, пусть
. Тогда искомая сумма выглядит так
1 0 1 1 1 0 1
0 1 0 1 1 1 0
0 0 1 0 1 1 1
0 0 0 1 0 1 1
0 0 0 0 1 0 1
0 0 0 0 0 1 0
0 0 0 0 0 0 1
Легко видеть, что каждый столбик отличается от столбика слева тем, что он сдвинут на одну строчку вниз и добавлен еще один битик. Поэтому сумма считается легко. Для того, чтобы не использовать доп. память, сначала первым проходом считаем сумму единиц в самом правом столбике. А потом начинаем "честное сложение столбиком". Сдвигаемся влево. Вычисляем сумму элементов этого столбика простым вычитанием одного бита из предыдущей суммы. Подсчитываем сколько "на ум пошло". Ну и тд.
Возможно, там еще надо рассмотреть пару "граничных" случаев, но это уже не принципиально. В целом же, вроде бы не слишком трудная задача.