f(k) - число чисел-палиндромов из k разрядов. Тогда
- f(2k) = 9·10k-1;
- f(2k + 1) = 9·10k.
Девятка отвечает за цифры старшего разряда - от единицы до девяти. Степень десятки - за остальные разряды из старшей половины числа.
g(k) - число чисел-палиндромов из не более чем k разрядов. Тогда
- g(2k) = 2·10k - 2;
- g(2k + 1) = 11·10k - 2.
Доказывается по индукции (g(n + 1) = g(n) + f(n + 1)).
h(n) - число чисел-палиндромов не более n. Я покажу на примере как его можно сосчитать быстро. Пусть n = 345678. Разобъём все палиндромы не более n на группы:
? - палиндромы длины один. Их f(1)
?? - палиндромы длины два. Их f(2)
??? - палиндромы длины три. Их f(3)
???? - палиндромы длины четыре. Их f(4)
????? - палиндромы длины пять. Их f(5)
1????1 - таких палиндромов 100 (все палиндромные цифровые строки длины 4)
2????2 - тоже самое (первые цифры от единицы до 3 - 1)
30??03 - таких палиндромов 10 (все палиндромные цифровые строки длины 2)
31??13 - тоже самое
32??23 - тоже самое
33??33 - тоже самое (вторые цифры от нуля до 4 - 1)
340043 - такой палиндром один (все палиндромные цифровые строки длины 0)
341143 - тоже самое
342243 - тоже самое
343343 - тоже самое
344443 - тоже самое (третьи цифры от нуля до 5 - 1)
345543 - такой палиндром один, но надо отдельно проверить
что он не больше n
Получается такая программа:
def ps_count(k):
""" число палиндромных строк длины k """
return 10 ** ((k + 1) // 2)
def p_count_10p(k):
""" число чисел-палиндромов не более k разрядов """
return 10 ** ((k + 1) // 2) + 10 ** (k // 2) - 2
def p_count(n):
""" число чисел-палиндромов не более n """
if n == 0:
return 0
digits = tuple(map(int, str(n)))
m = len(digits)
# короткие палиндромы
c = p_count_10p(m - 1)
for i in range((m + 1) // 2):
# палиндромы вида ABC????CBA
c += (digits[i] - (0 if i > 0 else 1)) * ps_count(m - 2 * (i + 1))
if digits[:m // 2 - 1::-1] <= digits[(m + 1) // 2:]:
# палиндром вида ABCDEEDCBA
c += 1
return c
def main():
n1, n2 = map(int, input().split())
# число чисел-палиндромов диапазоне [n1, n2]
print(p_count(n2) - p_count(n1 - 1))
main()
echo 1026376 1_000_000_000_000_000 | python pcount.py
109997973
Программа работает за логарифмическое время. Её можно переделать для расчёта суммы палиндромов. Первоначально так и было, но вопрос изменился и ответ упростился.