c++ У Анастасии есть целое положительное число, де...

Создано: 7 декабря 2025 г.

Отвечено с использованием GPT-5.1 Thinking от Chat01

Вопрос

c++ У Анастасии есть целое положительное число, десятичная запись которого не содержит нулей.

Борис хочет сделать Анастасии сюрприз и поставить ровно один знак + или * между какими-то двумя цифрами числа так, чтобы значение полученного выражения было чётным.

Сколькими способами он это может сделать? Два способа считаются разными, если используется разный знак, а также если знак стоит в разных позициях.

Формат входных данных
Первая строка входных данных содержит одно целое число
n
(
1

n
<
10
10
000
).
Формат выходных данных
Выведите одно целое число — количество способов сделать число Анастасии чётным с помощью указанного в задаче действия.
Система оценки
Задача состоит из четырёх подзадач.

В первой подзадаче
n
<
10
18
. Эта подзадача оценивается в 15 баллов.
Во второй подзадаче
n
<
10
100
. Эта подзадача оценивается в 34 балла.
В третьей подзадаче все цифры числа — единицы. Эта подзадача оценивается в 8 баллов.
В четвёртой подзадаче дополнительных ограничений нет. Эта подзадача оценивается в 43 балла.

Мысль

Breaking down the competitive programming task

The goal is to insert a '+' or '*' between two adjacent digits in a number (up to 10,000 digits) so that the resulting expression is even. We need to count how many pairs of positions and operators give an even result, keeping in mind the constraints about no leading zeros.

Optimizing the calculation with mod2 for evenness

Since the number is too large to handle directly, I’ll focus on the parities of the prefixes and suffixes. The parity of A plus B is determined by whether they share the same parity (even/odd), and the product is even if at least one of A or B is even. I’ll use dynamic mod2 to calculate and track this efficiently.

Simplifying the parity calculation

I realized the parity of a number in decimal depends only on its last digit. For prefixes, the parity is just the parity of the last digit, so no need for dynamic calculation after all. Similarly, for the suffix, the parity is fixed since it’s always determined by the last digit of the whole number.

Counting valid cuts for even expressions

For each cut, I’ll compute the parities of A and B. A's parity comes from the digit at position i, and B's parity is determined by the last digit. Then, based on the operator, I can count how many valid ways there are to make the expression even, considering the required parity conditions for '+' and '*'. I’ll precompute counts of even and odd positions to simplify this.

Counting valid operations based on digit parity

For each digit, I’ll check whether inserting '+' or '*' results in an even value based on whether the prefix and suffix parities match. The key insights: when the last digit is even, the '+' operation depends on even digits up to that point. When the last digit is odd, the total count simplifies to L-1 regardless of the digits.

Final steps to compute the answer

For each case, I will calculate the total valid operations based on the last digit's parity. The maximum length of the number is 10,000 digits, so the range isn't too large. Even with 10,000 digits, calculations are manageable, and the result will fit in a 32-bit integer.

Verifying algorithm and logic

I’m verifying that the formula works for different cases by checking smaller examples. For example, with digits 1,3,7, I computed the ways for sums and products, validating that the logic holds. The formula also correctly returns 0 for edge cases with one-digit numbers. Complexity is intuitive: O(L), where the length L of the number is manageable even for large inputs.

Thought for 31s

Ответ

Решается это довольно коротко 😊

Идея

Пусть число — это строка цифр
s1s2sLs_1 s_2 \dots s_L, где LL — количество цифр.

Мы ставим одну операцию + или * между цифрами sis_i и si+1s_{i+1}. Тогда выражение выглядит так:

A op BA \ \text{op} \ B

где:

  • AA — число из первых ii цифр,
  • BB — число из оставшихся цифр.

Нас интересует, когда A+BA + B или ABA \cdot B чётно.

Наблюдение 1: чётность числа по десятичной записи

Чётность любого числа в десятичной системе полностью определяется последней цифрой.
То есть:

  • чётность AA = чётность цифры sis_i (последняя цифра в префиксе),
  • чётность BB = чётность цифры sLs_L (последняя цифра всего числа, она же последняя цифра любого суффикса).

Значит, для позиции разреза ii:

  • parity(A)=parity(si)\text{parity}(A) = \text{parity}(s_i),
  • parity(B)=parity(sL)\text{parity}(B) = \text{parity}(s_L)одна и та же для всех разрезов.

Обозначим:

  • pA=p_A = чётность AA,
  • pB=p_B = чётность BB (зависит только от последней цифры исходного числа).

Наблюдение 2: условия чётности операций

  • A+BA + B чётно ⇔ pA=pBp_A = p_B (сумма двух чисел одинаковой чётности).
  • ABA \cdot B чётно ⇔ хотя бы одно из чисел чётно
    pA=0p_A = 0 или pB=0p_B = 0.

Теперь рассмотрим два случая.


Случай 1: последний разряд чётный (суффикс всегда чётный)

Пусть pB=0p_B = 0 (последняя цифра чётная).

Для каждой позиции ii (от 1 до L1L-1):

  • + даёт чётное число, если pA=0p_A = 0 (т.е. цифра sis_i чётная).
  • * всегда даёт чётное число, потому что BB уже чётное.

Обозначим:

  • evenCnt — количество чётных цифр среди s1,...,sL1s_1, ..., s_{L-1}.

Тогда:

  • количество подходящих + = evenCnt,
  • количество подходящих * = L1L - 1 (по одной позиции на каждый разрез).

Итого:

answer=evenCnt+(L1)\text{answer} = \text{evenCnt} + (L - 1)

Случай 2: последний разряд нечётный (суффикс всегда нечётный)

Пусть pB=1p_B = 1 (последняя цифра нечётная).

Для каждой позиции ii:

  • + чётное ⇔ pA=1p_A = 1 (т.е. цифра sis_i нечётная),
  • * чётное ⇔ pA=0p_A = 0 (т.е. цифра sis_i чётная), так как BB нечётно.

Т.е. для каждого разреза ровно одна из двух операций делает результат чётным.
Всего разрезов L1L - 1, значит:

answer=L1\text{answer} = L - 1

(независимо от самих цифр, важна только нечётность последней).


Итоговая формула

Пусть:

  • L = s.size(),
  • lastEven = (последняя цифра чётная?),
  • evenCnt = количество чётных цифр среди первых L-1 цифр.

Тогда:

  • если lastEven == trueanswer = evenCnt + (L - 1),
  • иначе → answer = L - 1.

Число цифр максимум 10 000, ответ ≤ 2·(L−1) < 20 000 — отлично помещается в int или long long.


Реализация на C++

cpp
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); string s; if (!(cin >> s)) return 0; int L = (int)s.size(); if (L == 1) { // Нет места, куда ставить знак cout << 0 << '\n'; return 0; } bool lastEven = ((s.back() - '0') % 2 == 0); int evenCnt = 0; for (int i = 0; i < L - 1; ++i) { int d = s[i] - '0'; if (d % 2 == 0) ++evenCnt; } long long ans; if (lastEven) { ans = evenCnt + (L - 1); } else { ans = (L - 1); } cout << ans << '\n'; return 0; }

Если хочешь, могу ещё приписать несколько маленьких тестов для самопроверки.

Поделиться этим Q&A