Для целого положительного числа x определим R(x) к...

تم الإنشاء في: ٣ مارس ٢٠٢٥

تمت الإجابة باستخدام O1 بواسطة Chat01

سؤال

Для целого положительного числа x определим R(x) как число, равное перевёрнутому x в десятичной записи. Например, R(123) = 321, R(1) = 1, а R(100500) = 5001.

Для данного числа S вычислите количество целых x таких, что 1 ≤ x и x+R(x) ≤ S.

В качестве ответа выведите остаток от деления этого количества на 10^9 + 7.

Всё бы ничего, но вот ограничения на S (0 < S < 10^100 000).

الفكرة

Mapping out big numbers

OK, let me see. The task is to count integers x such that x + R(x) is less than or equal to S, even though S can be as large as 10^100000.

Analyzing digit constraints

I'm focusing on digit-by-digit analysis, ensuring sums hover around n or n+1 digits. The large size of S means a standard DP approach may be impractical.

Assessing digit-based methods

I'm noting a standard digit DP approach, focusing on states and carry sums. Considering palindromes as a simplified method to manage digit constraints and sum calculations.

Reshaping my approach

I’m thinking about examining the symmetry of digit sums and exploring simpler methods, like defining the function f(x) = x + R(x), to efficiently count valid x values.

Charting a course

I'm working through a digit DP strategy, building x from left to right, accounting for carries, and determining if x + R(x) ≤ S. Progress is steady and methodical.

Harmonizing digits

I'm aligning x's digits from both ends, ensuring their sum fits within constraints. This method simplifies the task, making it easier to handle large values of S.

Constructing the DP mechanism

I'm detailing a dynamic programming method to build x, ensuring symmetry with R(x) and managing carry sums, all while keeping x + R(x) within S's limits.

Mapping out digit DP

I'm pulling together a digit DP method to generate x, ensuring x + R(x) stays within the confines of S up to n digits, avoiding over iteration of x.

Building a DP

I’m constructing a dynamic programming approach to count x, ensuring x + R(x) ≤ S, and limiting the sum to n digits or fewer. Progressing thoughtfully from the highest digit to the lowest.

Piecing together combinations

Piecing together x's digits, I’m sparking interest in digit DP to ensure pairs sum to S. If k is odd, let's handle the middle digit carefully.

Mapping digit alignment

I'm piecing together a method to match x's digits with S, managing the carry from the right side while ensuring each digit sum aligns with the corresponding digit from S.

Charting reversed indices

I’m thinking through digit-by-digit alignment from right to left, managing carries. Starting with x_{k-1} + x_0, I move leftward, carefully managing carries for precision.

Balancing symmetry

I’m aligning pairs of digits (x_i, x_{k-1-i}), managing the carry, and keeping track of S's prefix. Avoiding over-complication, I ensure x + R(x) ≤ S.

Weighing DP methods

I'm evaluating the feasibility of a digit DP approach for managing partial sums up to 100,000 digits. Complexity and state management are significant factors here.

Assessing tight constraints

OK, let me see. Considering carry states of 0 or 1 is manageable with partial sums of 19. This keeps the computational load reasonable and the problem solvable.

Balancing digit pairs

I’m aligning digits x_i and x_{k-1-i} with S's i-th digit, considering leading zeros and carry to ensure the sum is consistent with S's prefix.

Mapping progress

OK, I’m working through the complexity and figuring out how to align digits of S with the sum, considering carry and prefix constraints, and optimizing digit choices effectively.

Evaluating digit DP

I'm thinking through digit DP, working through x_i choices to keep sums under S's constraints, carefully managing carry and aligning with S's prefix.

Navigating digit sum constraints

I'm piecing together a dynamic programming method to keep x and R(x) within digit sum constraints using "half-sums." This approach effectively manages large integers too.

Building the function

I’m working on a digit DP function f(T) to tally valid x values, ensuring x + R(x) stays under a specific T. This method effectively manages large integers.

Evaluating digit pairs

I'm summing valid digit pairs x_i and x_{n-1-i} for each position to ensure their sum aligns with the modified DP function, accounting for previously calculated pairs.

'Tackling middle digit complexity

I'm thinking through managing the middle digit when n is odd. This involves ensuring the sum of valid digit pairs adheres to the constraints of the dynamic programming method.

Crafting the DP framework

I’m setting guidelines for valid x numbers by focusing on digit pairs and ensuring their sum respects T's digit structure. Carry and less constraints guide this refinement.

Navigating middle digit impact

Interestingly enough, the middle digit's influence is considered either at the start or end, seamlessly integrating it into the digit DP function.

Refining digit processing

In this approach, pairs of digits are carefully chosen and summed, with the middle digit singled out in odd-length numbers. ซ.linearly comparing the outcomes with digits from T ensures the sums are consistent.

Ensuring alignment

I’m working through digit pairs to align their sum with T's digits, maintaining the match state. Finished, I verify if the final carry results in an n-digit sum.

Ensuring transitions

I’m refining the DP transition by checking the sum digit modulo 10 against T's digit. If they match, we proceed; if they don’t, we exit. Accumulating valid ways is next.

Advancing the DP strategy

The focus is on summing pair digits, checking modulo constraints, and moving forward with valid transitions, noting when constraints are relaxed.

Counting digit pairs

I’m thinking through how to tally digit pairs that total a specific sum. For sums between 0 and 9, there are s+1 pairs; for 10 to 18, 19-sum pairs.

Understanding digit pairs

I’m establishing a dynamic programming method to align digit pairs and the middle digit with T's digits. The base case starts with dp(0,0,0)=1, and the transition is defined accordingly.

Aligning with rules

I’m connecting digit pairs and middle digits to T's digits, ensuring valid progression based on constraints. This method effectively incorporates all necessary transitions for the specified conditions.

Breaking down digit pairs

I’m organizing a plan to digitize and prioritize detecting digit pairs and middle digits from T's digits. This step enhances the dynamic programming approach's efficiency by focusing on accurate digit alignment.

Plotting future states

Mapping out digit pairs and transitions for each state. Validating sums for potential next states and integrating them efficiently into the dynamic programming solution.

Mapping transitions

I’m precomputing valid transitions for each state, allowing quick O(1) transitions in the less=1 case and more meticulous handling for the less=0 case.

Navigating complexity

Handling digit pairs and transitions effectively, while managing constraints and implementing efficient coding practices. This approach ensures the solution adheres to overall time and space complexity.

Mapping the strategy

I’m outlining the DP transitions, ensuring digit limits and constraints are met. This approach efficiently manages state changes based on the context and digit constraints.

Ensuring digit accuracy

I’m confirming the approach aligns with valid sums, using the correct digit arrays, and handling leading zeros seamlessly. Parsing T's digits and progressing steps align perfectly with the plan.

Mapping transitions

I’m piecing together dynamic programming transitions, defining state changes, and preparing transition arrays to efficiently manage constraints and ensure accuracy throughout the process.

Translating the solution

I’m explaining the Python implementation, focusing on managing transitions and constraints. Starting with a single digit example, I’ll guide the progression and ensure accurate state management.

Addressing edge cases

I'm spotting issues with all-zero digits. If their sum is within T, I'll exclude them from the count, ensuring leadings zeros don't skew the final answer.

Taking a closer look

I’m validating the DP approach with T=1 and T=2, ensuring it accurately handles x=0 and x>=1 cases, subtracting valid sums to align with constraints.

Clarifying digit alignment

I’m digging into how the DP approach handles pairs of digits from T. Despite the challenge of ignoring the second digit, the method still ensures valid sum management.

Evaluating sum dynamics

I'm breaking down the nuances of final carries and their impact on sum digits, which often result in 2 or 3-digit sums depending on whether the digit is below or above 10.

Pulling together

I’m examining sums to pinpoint valid x values where x+R(x) meets constraints, ultimately identifying six valid x values: 1 to 5 and 10.

Aligning digit pairs

OK, let's confirm the correctness of the DP method by aligning pairs of digits from T and x, ensuring valid sums strictly less than or equal to T. Progress is being made with each step.

Accounting for carries

Hm, that’s interesting. I’m thinking through how the carry's influence on the sum's digit is handled in the DP approach, which might skip or assess the second digit of T.

Revisiting digit handling

I’m rethinking the digit-by-digit evaluation, considering the carry and partial sums from the rightmost digits of both T and x to ensure consistent and valid sums.

Ensuring alignment

OK, I’m setting up the DP strategy to pair each x_i digit with x_{n-1-i} and handle the midpoint for odd n to maintain sum consistency with T.

Ensuring digit count

I'm correcting my approach by making sure the sum has exactly n digits, avoiding a final carry to keep pairs of digits aligned. This leads to a balanced solution.

Taking a closer look

I’m thinking through how to manage the final digit from the carry, ensuring it aligns with T. This approach should provide a clear, consistent method throughout.

Tracking carry accuracy

I’m focusing on how the carry from the first step determines the second digit, making comparisons with T's second digit to ensure precise alignment and no involving new x digits.

Handling leftover digits

OK, let me see. I’m working through the extended DP method, ensuring each digit compares with T's, sticking with x digits for leftover spots, and accurately reflecting the sum's structure.

Balancing digits

OK, let me see. I’m aligning the sum's digit count with T by handling leftover digits for an odd n, ensuring each digit’s value is compared accurately.

Mapping the way

I’m unveiling a refined method to sum digits by integrating a final step that ensures the total has n digits, guaranteeing precision and adherence to the specifications provided.

Shaping the DP array

I’m constructing a dynamic programming array with specific dimensions to manage leftover digits. This method ensures accurate alignment with T's digits.

Ensuring accuracy

I'm finalizing the dynamic programming setup to manage leftover digits, making sure the sum has n digits and aligns with T's digits. This approach keeps precision intact throughout.

Navigating expansion challenges

Interestingly enough, I'm thinking through the expanded dynamic programming array's size, optimizing transitions to maintain feasibility in Python, and exploring prefix sums for quicker computation. Progress is steady and promising.

Reasoned about problem involving reversed digits for 2m 2s

الإجابة

Ниже изложена идея того, как можно решить задачу, даже когда SS (порог суммы x+R(x)x + R(x)) имеет до 10510^5 десятичных цифр. Ключ состоит в аккуратном «DP по цифрам» (digit DP), где мы перебираем возможные «половинки» числа xx и одновременно следим, чтобы сумма x+R(x)x + R(x) не превосходила SS.

Постановка задачи ещё раз

Нужно найти количество целых положительных xx, таких что

  1. x1x \ge 1,
  2. x+R(x)Sx + R(x) \le S,

где R(x)R(x) — это «перевёрнутое» xx в десятичной записи (например, R(123)=321R(123) = 321, R(100500)=5001R(100500) = 5001).
Ответ требуется вывести по модулю 109+710^9 + 7. Число SS задано в виде строки длиной до 10510^5 цифр, т.е. прямой перебор всех xx невозможен.

Главная идея: «парное» сложение цифр при x+R(x)x + R(x)

Запишем xx ровно в nn цифрах, допуская ведущие нули (где nn — это число цифр в SS). Ясно, что если x+R(x)x+R(x) имеет не более nn цифр, то xx нельзя брать длиннее nn (иначе сумма могла бы «выйти» за n+1n+1 цифр).

Пусть n=Sn = \lvert S \rvert. Нумеруем цифры SS (и вообще числа) справа налево, от индекса 00 до n1n-1. Обозначим:

  • tit_iii-я (считая от права к леву) цифра числа SS. То есть t0t_0 — самая «младшая» (правая) цифра SS, tn1t_{n-1} — старшая (левая).

Рассмотрим десятичную запись xx длины nn (с ведущими нулями). Тогда «перевёрнутое» xx — это те же цифры, но в обратном порядке.
Если мы смотрим на сумму

x+R(x),x + R(x),

то её ii-я цифра (считая справа налево) получается как

(xi+xn1i+(перенос из предыдущего разряда))mod10,\bigl(x_i + x_{n-1-i} + \text{(перенос из предыдущего разряда)}\bigr) \bmod 10,

а перенос в следующий (более левый) разряд есть

xi+xn1i+carry10.\left\lfloor \frac{x_i + x_{n-1-i} + \text{carry}}{10} \right\rfloor.

При этом:

  • Если i<n1ii < n-1-i, мы действительно берём пару «зеркальных» цифр xix_i и xn1ix_{n-1-i}.
  • Если i=n1ii = n-1-i (это бывает, когда nn нечётно и ii — это «средний» индекс), тогда «пара» сливается в одну цифру xix_i, и в сумму входит xi+xn1i=2xix_i + x_{n-1-i} = 2 x_i.

Но ключевой момент: чтобы в сумме получилось ровно nn цифр (а не n+1n+1), в самом старшем разряде перенос (carry) в конце должен быть 0. Иначе сумма выйдет за nn-значный предел и гарантированно превысит SS, если у SS тоже nn цифр.

Схема DP

  1. Разобьём сумму на «движение» по разрядам справа налево.
    У числа из nn цифр «пар» (или «полупар») будет n2\bigl\lfloor \tfrac{n}{2}\bigr\rfloor штук, плюс одна «серединная» цифра, если nn нечётно. То есть всего шагов, где мы «выбираем цифры xix_i» (или пару цифр), будет

    half=n2=n+12.\text{half} = \left\lceil \frac{n}{2} \right\rceil = \frac{n+1}{2}.

    (Это количество «разрядов», которые действительно формируются за счёт цифр xx.)

  2. После того, как мы «потратили» все цифры xx (то есть прошли half\text{half} таких шагов), могут остаться «верхние» разряды суммы (если nn чётно, это n2\frac{n}{2} пар; если нечётно, n12\frac{n-1}{2} пар плюс один средний разряд). На оставшихся более левых разрядах в самой сумме уже «не участвуют никакие новые цифры xx», потому что все nn цифр xx уже учтены. Там в сумме может остаться лишь перенос (carry), который постепенно «перетекает» дальше влево.

    • На каждом таком «лишнем» шаге сумма-разряд равна просто «текущий перенос carry» (плюс 0 от цифр xx, так как там уже их нет), а новый перенос станет 0.
  3. Сравнение с SS.
    Мы ведём состояние «флаг меньше» (условно less), означающий, что уже на каком-то предыдущем (более младшем) разряде сумма была строже меньше соответствующего префикса SS. Если мы ещё «не отстали» (т.е. less = 0), то очередная цифра суммы не должна превышать соответствующую цифру tit_i. Если меньше — то переходим в состояние less = 1. Если ровно равна — состояние less не меняется. Если пытались сделать больше — переход невозможен.

  4. Перенос (carry) может быть только 0 или 1 (ведь сумма двух цифр 9+9=18\le 9 + 9 = 18, плюс перенос 1 даёт максимум 19, что даёт перенос не больше 1).

  5. DP по парам

    • Когда обрабатываем «обычный» шаг (не середина) с индексом ii (справа налево), мы выбираем пару цифр (d1,d2)(d_1, d_2) в [0..9]×[0..9][0..9]\times [0..9], чтобы их сумма d1+d2d_1 + d_2 вместе с переносом c дало «цифру» (младший разряд) ti\le t_i (если less=0) или любую (если less=1).
    • Если nn нечётно и мы подходим к серединному индексу (когда ii совпадёт с n12\frac{n-1}{2}), берём одну цифру dd и считаем 2d+c2d + c.

    После этого шага получаем «цифру суммы» digit=(sum+c)mod10\mathit{digit} = (\,\mathit{sum}+c) \bmod 10 и «новый перенос» next_carry=(sum+c)/10\mathit{next\_carry} = \lfloor(\mathit{sum}+c)/10\rfloor. Сравниваем digit\mathit{digit} с tit_i (если less=0). Определяем, переходим ли в less = 1 (если digit<ti\mathit{digit} < t_i) или остаёмся в less = 0 (если digit=ti\mathit{digit} = t_i), или переход невозможен (если digit>ti\mathit{digit} > t_i).

    Так мы дойдём до i=half1i = \text{half}-1. В этот момент мы исчерпали все «живые» цифры xx.

  6. Обработка «остаточных» разрядов
    Начиная с i=halfi = \text{half} и далее до n1n-1, в сумме новые цифры xx не появляются (мы уже «ушли» за середину — все пары/серединная цифра учтены). Значит, сумма-разряд равен просто переносу carry (0 или 1), а на следующий разряд перенос обнулится.

    • Поэтому нам нужно «пройтись» от i=halfi = \text{half} до n1n-1, сравнивая carry с tit_i (если ещё не перешли в less=1). После чего carry станет 0, и идём дальше, пока не дойдём до старших разрядов.
    • Если на каком-то шаге (при less=0) перенос carry окажется больше, чем ti\,t_i, ветка невозможна. Если меньше — сразу less=1. Если равно — less=0 сохраняется. После этого шага (разряда) перенос всегда «гаснет» (становится 0), потому что мы добавляем только 0 к нему.
    • Идём так до i=ni = n. В конце, если перенос опять почему-то не 0 (теоретически уже не должен быть), значит сумма вышла за nn-значный диапазон — это отбрасываем.
  7. Учёт условия x1x \ge 1.
    Поскольку мы разрешили у xx ведущие нули, в нашу DP-переборку попадёт и «число» x=00x=0\ldots0 (все нули). Его сумма с разворотом тоже будет 0, что, конечно, S\le S, но нарушает условие x1x \ge 1. Поэтому из ответа придётся вычесть 1, если сумма нуля действительно не превосходит SS (а она не превосходит, если S0S\ge 0, но в условии S>0S>0, так что действительно нужно вычитать 1).

  8. Сложность.

    • В «парной» части (до середины) у нас half=n2\text{half} = \lceil \tfrac{n}{2}\rceil шагов. На каждом шаге, если мы ещё не «отстали» от SS (less=0), нам приходится перебирать все возможные суммы двух цифр (или удвоенной одной цифры) от 0 до 18 и смотреть, какой получится digit\mathit{digit}. Но это можно зашить в заранее посчитанные массивы переходов (чтобы каждый шаг делался за O(1)O(1) , аккуратно суммируя количество пар, дающие нужную сумму). При less=1 мы вообще не сравниваем с tit_i и можем сложить «оптом» все варианты.
    • После середины у нас ещё nhalfn - \text{half} шагов, на каждом мы лишь сравниваем перенос (0 или 1) с соответствующей цифрой tit_i — это O(1)O(1) операция.

    Итого всё укладывается в примерно O(n)O(n) или O(n)O(n) с небольшой константой, что при nn до 10510^5 реализуемо на практике (особенно на языках вроде C++). В Python потребуется аккуратная оптимизация (использование списков/массивов, предвычисление переходов, и т.д.), но тоже сделать можно.

Итоговый план решения

  1. Считать SS как строку, сохранить её длину nn.

  2. Записать цифры SS в массив {t0,,tn1}\{t_0,\dots,t_{n-1}\} в обратном порядке (чтобы t0t_0 был младшим разрядом).

  3. Подготовить вспомогательные массивы:

    • pairCount[ s ] = число пар (d1,d2)(d_1,d_2) с 0d1,d290 \le d_1,d_2 \le 9, у которых d1+d2=sd_1 + d_2 = s. Это для «обычных» пар разрядов.
    • symCount[ s ] = число цифр d[0..9]d\in[0..9], таких что 2d=s2d = s. Это для «серединной» цифры при нечётной длине.
    • (Возможна ещё более хитрая предвычисленная таблица, которая сразу говорит «если текущий перенос cc и мы хотим получить после прибавки cc к сумме ss результат digit=(s+c)mod10\mathit{digit} = (s+c) \bmod 10 и следующий перенос (s+c)//10(s+c)//10, то …», но можно обойтись и простым перебором s=0..18s = 0..18.)
  4. Основной DP №1 (до «середины»), храним dp[i][carry][less] — сколько есть способов «дописать» пары (или одну цифру, если это серединный шаг), чтобы сформировать разряды суммы от 0-го до i1i-1-го согласованно с ограничением t0..ti1\le t_0..t_{i-1}.

    • База: dp[0][0][0] = 1 (никаких цифр не выбрали, перенос 0, ещё не отстали от SS). Остальные по 0.
    • Идём ii от 0 до half1\text{half}-1. Определяем, «середина» ли это, исходя из чётности nn и ii.
    • Перебираем текущее состояние (carry,less)(carry, less). Затем перебираем все суммы ss (либо от удвоенной цифры, либо от пары) = 0..18.
      • digit=(s+carry)mod10\mathit{digit} = (s + carry) \bmod 10.
      • next_carry=(s+carry)/10\mathit{next\_carry} = \lfloor (s + carry)/10\rfloor.
      • Если less=0, сравниваем digit\mathit{digit} c tit_i. Если digit>ti\mathit{digit} > t_i — пропускаем, если digit<ti\mathit{digit} < t_i — следующий less=1, иначе less=0.
      • Прибавляем к dp[i+1][ next_carry ][ next_less ] количество способов выбрать (пару или одиночную цифру), которые дают сумму ss.
    • В итоге получим dp[ half ][ c ][ l ].
  5. Переход ко второй фазе (DP №2) — «доливание» оставшихся разрядов, где новых цифр xx уже нет, а в сумме идёт только перенос.

    • В качестве начальных состояний берём все (dp[half][c][l])\bigl(dp[\text{half}][c][l]\bigr) из предыдущей DP.
    • Затем для ii от half\text{half} до n1n-1 «цифра суммы» есть просто carry. Новый перенос после такого разряда всегда 0, потому что к carry мы больше ничего не добавляем.
      • Если less=0, сравниваем carry с tit_i. Если carry>t_i\), путь невозможен. Если carry<t_i), то в следующее состояние less=1. Если carry=t_i, то less=0 сохраняем.
    • Получаем dp2[n][ final_c ][ final_less ]. При i=ni=n (вышли за старшие разряды) перенос final_c должен быть 0 (иначе получилось бы n+1n+1-значное число, не подходящее под S\le S).
    • Суммируем dp2[n][0][0] + dp2[n][0][1] — это число способов задать xx (включая нулевой xx), чтобы x+R(x)Sx+R(x) \le S.
  6. Вычитаем 1 (если S0S \ge 0, что в задаче всегда так) — это исключает «число» xx, состоящее из одних нулей, так как оно не удовлетворяет x1x\ge 1.

  7. Результат берём по модулю 109+710^9+7.

На практике вся эта логика упирается примерно в O(n)O(n) итераций, где на каждой «парной» итерации мы делаем фиксированное число проверок (перебор сумм 0..18 и т.д.), а на «доливающих» шагах — вообще O(1)O(1) действий. При nn до 10510^5 это объём порядка нескольких миллионов элементарных операций — реализовать можно. В языках компилируемого типа (C++/Rust) обычно без проблем; в Python нужно будет чуть аккуратнее оптимизировать, но тоже выполнимо.


Пример на коротком SS

Возьмём S=11S=11. Тогда n=2n=2, цифры SS «справа налево» будут t0=1,t1=1t_0=1, t_1=1.

  • half=22=1\text{half} = \lceil\frac{2}{2}\rceil=1. Значит, в первой фазе у нас будет всего i=0i=0 (одна итерация) — «берём пару цифр x0,x1x_0, x_1».

    Пусть dp[0][0][0]=1\text{dp}[0][0][0]=1. Рассмотрим все пары (d1,d2)(d_1,d_2) с суммой s=d1+d2[0..18]s = d_1+d_2\in[0..18].

    • digit=(s+carry)mod10=smod10\mathit{digit} = (s+ carry)\mod 10 = s\mod 10 (так как carry=0).
    • next_carry=s//10\mathit{next\_carry} = s//10 (0 или 1).
    • Сравниваем digit\mathit{digit} с t0=1t_0 = 1.
      • Если digit>1\mathit{digit} >1, пропускаем.
      • Если digit=1\mathit{digit} =1, переходим в dp[1][next_carry][0]\text{dp}[1][ \mathit{next\_carry}][0].
      • Если digit<1\mathit{digit} <1, переходим в dp[1][next_carry][1]\text{dp}[1][ \mathit{next\_carry}][1].

    Например, digit=0\mathit{digit} =0 (то есть s=0s=0): это даёт digit<1\mathit{digit}<1, значит less=1. А сколько пар (d1,d2)(d_1,d_2) имеют сумму 0? Ровно 1 (это d1=0,d2=0d_1=0, d_2=0). Тогда next_carry=0\mathit{next\_carry}=0. Итак, dp[1][0][1]+=1\text{dp}[1][0][1] += 1.

    digit=1\mathit{digit} =1 (то есть s=1s=1): пар сумма=1 ровно 2 — это (0,1)(0,1) и (1,0)(1,0). Тогда dp[1][0][0]\text{dp}[1][0][0] увеличится на 2.

    digit>1\mathit{digit} >1 — пропускаем, так что суммы s2s\ge2 не пройдут при less=0.

    Итого после первого шага:

    • dp[1][0][0]=2\text{dp}[1][0][0] = 2. (это соответствует сумме-разряду =1=1, перенос 0)
    • dp[1][0][1]=1\text{dp}[1][0][1] = 1. (это соответствует сумме-разряду =0=0, перенос 0)
    • Остальные нули.
  • Теперь вторая фаза — «обрабатываем верхние разряды» с i=1i=1 до n1=1n-1=1. Это всего один разряд i=1i=1.
    Здесь «сумма-разряд» равен текущему carry. А нового переноса уже не будет — после добавления нуля он обнуляется.

    Смотрим, какие есть dp[1][carry][less]\text{dp}[1][ carry ][ less].

    1. dp[1][0][0]=2\text{dp}[1][0][0] = 2. Значит, сейчас carry=0, less=0.

      • Сумма-разряд digit = carry=0. Сравниваем с t1=1t_1=1. Получаем digit < t_1, значит переходим в less=1, перенос становится 0.
      • Добавляем эти 2 в dp2[2][0][1]\text{dp2}[2][0][1].
    2. dp[1][0][1]=1\text{dp}[1][0][1] = 1. Значит, сейчас carry=0, less=1.

      • Если уже less=1, мы не ограничены t1t_1. digit=0. Перенос будет 0. Остаётся less=1.
      • Добавляем 1 в dp2[2][0][1]\text{dp2}[2][0][1].

    Итого dp2[2][0][1]\text{dp2}[2][0][1] получаем 2+1=32 + 1 = 3. Всё остальное — по нулям.

  • Теперь мы вышли за старшие разряды i=2i=2. По условию финальный перенос должен быть 0. Тогда складываем dp2[2][0][0]+dp2[2][0][1]\text{dp2}[2][0][0] + \text{dp2}[2][0][1]. Первое равно 0, второе — 3. Итого 3.

  • Вычитаем 1 за нулевой xx. Получается 2.

Проверим вручную, какие xx (двухзначные, разрешая ведущие нули) дают x+R(x)11x+R(x) \le 11, причём x1x\ge1.

  • x=01x=01 (это десятичное 1). Сумма 1+1=2111+1=2\le11.
  • x=10x=10. Сумма 10+01=111110+01=11\le11.
  • x=00x=00 (ноль) даёт сумму 0 — мы его исключаем.
  • x=02x=02 даёт сумму 2+20=22>112+20=22>11 — не подходит.
  • x=11x=11 даёт 11+11=22>1111 + 11=22>11. И т.д.

Получились ровно x=1x=1 и x=10x=10. То есть 2 штуки — сходится с расчётом.

(Заметьте, если отдельно пройтись по всем x199x\ge1\le 99, то мы найдём ещё x=2,3,4,5x=2,3,4,5 вроде бы дают 2+2=42+2=4, 3+3=63+3=6, … Но надо помнить, что мы рассматриваем xx ровно как «двухзначное» с ведущими нулями. Например, x=2x=2 — это «02»; тогда сумма 02+20=22>1102 + 20=22>11. Значит, «02» не годится. А вот x=1x=1 — это «01» и действительно «01 +10=11», ошибка? Посчитаем аккуратнее: «01» в прямом десятичном смысле — это 11. Его перевёрнутая запись «10» — это 10\mathbf{10} (десять). Сумма 1+10=111+10=11. Всё верно, значит для «1» это считается как (цифры 0101) + (цифры 1010) = 11. А вот «02» в перевёрнутом виде «20» сумма 22, что уже не проходит. Аналогично «03» + «30»=33 и т.д. Только «05» + «50»=55 … все мимо.)

Таким образом, всё согласуется.


Итог

  • Реализовать описанный двухфазный DP (с аккуратным учётом «пар» или «серединной» цифры) вполне возможно при nn до 10510^5.
  • Итог берётся по модулю 109+710^9+7.
  • Не забыть вычесть 1, исключая «все цифры xx = 0&raquo;.

Такое решение укладывается в асимптотику O(n)O(n) (с небольшой константой ~19 при обработке пар), и позволяет обработать даже гигантское SS (длиной до сто тысяч цифр).

مشاركة هذا السؤال والجواب