В данной статье мы подробно разберем популярную алгоритмическую задачу, в которой нужно определить, загадает ли Вася желание, основываясь на свойствах цифр трехзначного числа; Задача является классическим примером проверки условий делимости и работы с цифрами числа․
���� Условие задачи
Легенда: Вася любит математику и верит в приметы, которые придумывает сам․ Когда он видит номер машины или квартиры из трёх цифр, он складывает цифры попарно (a+b, b+c, a+c)․ Если хотя бы одна из этих сумм делится на три, Вася загадывает желание․
Входные данные: Три целых числа a, b, c (цифры от 0 до 9)․
Выходные данные: Слово «да», если Вася загадает желание, и «нет» в противном случае․
Примеры
| Ввод | Пояснение | |
|---|---|---|
2 2 2 | нет | Суммы: 2+2=4, 2+2=4, 2+2=4․ Ни одна не делится на 3․ |
1 2 3 | да | Суммы: 1+2=3 (делится на 3), 2+3=5, 1+3=4․ Условие выполнено․ |
0 0 0 | да | Суммы: 0+0=0․ Ноль делится на любое число, в т․ч․ на 3․ |
9 9 9 | да | Суммы: 9+9=18․ 18 делится на 3․ |
���� Математический анализ и логика решения
На первый взгляд, задача требует просто перебрать три пары и проверить делимость․ Однако, зная свойства делимости, можно найти более элегантное и быстрое решение․
Свойство делимости суммы
Сумма двух чисел делится на 3 тогда и только тогда, когда сумма их остатков от деления на 3 делится на 3․
Пусть r_a = a % 3, r_b = b % 3, r_c = c % 3․ Остатки могут быть только 0, 1 или 2․
Нам нужно проверить, существует ли пара, сумма остатков которой равна 0 или 3 (то есть 0 по модулю 3)․
Возможные выигрышные комбинации остатков:
- Два нуля (0, 0): 0 + 0 = 0 → делится на 3․
- Единица и двойка (1, 2): 1 + 2 = 3 → делится на 3․
Следовательно, Вася загадает желание («да») в двух случаях:
- Среди цифр есть хотя бы две, которые делятся на 3 (остаток 0)․ Цифры: 0, 3, 6, 9․
- Среди цифр есть хотя бы одна с остатком 1 (цифры: 1, 4, 7) И хотя бы одна с остатком 2 (цифры: 2, 5, 8)․
Во всех остальных случаях ответ — «нет»․
���� Алгоритм решения
- Считать три целых числа a, b, c․
- Посчитать количество чисел, дающих остаток 0, 1 и 2 при делении на 3․
- cnt0 — количество чисел с остатком 0․
- cnt1 — количество чисел с остатком 1․
- cnt2, количество чисел с остатком 2․
- Проверить условие:
(cnt0 >= 2) OR (cnt1 >= 1 AND cnt2 >= 1)․ - Если условие истинно — вывести «да», иначе — «нет»․
Альтернативный (наивный) алгоритм, просто проверить три суммы напрямую․ Для трех чисел это абсолютно допустимо и работает за O(1)․
if (a + b) % 3 == 0 or (b + c) % 3 == 0 or (a + c) % 3 == 0:
print("да")
else:
print("нет")
���� Примеры реализации на популярных языках
Python 3
def solve:
# Считываем три числа из одной строки
a, b, c = map(int, input․split)
# Прямая проверка попарных сумм
if (a + b) % 3 == 0 or (b + c) % 3 == 0 or (a + c) % 3 == 0:
print("да")
else:
print("нет")
if __name__ == "__main__":
solve
C++ (GNU C++17)
#include <iostream>
using namespace std;
int main {
// Ускорение ввода/вывода
ios_base::sync_with_stdio(false);
cin․tie(NULL);
int a, b, c;
if (cin >> a >> b >> c) {
// Проверка через остатки (оптимизированный вариант)
int cnt[3] = {0, 0, 0};
cnt[a % 3]++;
cnt[b % 3]++;
cnt[c % 3]++;
if (cnt[0] >= 2 || (cnt[1] >= 1 && cnt[2] >= 1)) {
cout << "да" << endl;
} else {
cout << "нет" << endl;
}
}
return 0;
}
Java (Java 11+)
import java․util․Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System․in);
int a = scanner․nextInt;
int b = scanner․nextInt;
int c = scanner․nextInt;
// Наивная проверка, максимально читаемая
if ((a + b) % 3 == 0 || (b + c) % 3 == 0 || (a + c) % 3 == 0) {
System․out․println("да");
} else {
System․out․println("нет");
}
scanner․close;
}
}
JavaScript (Node․js)
const readline = require('readline');
const rl = readline․createInterface({
input: process․stdin,
output: process․stdout
});
rl․on('line', (line) => {
const [a, b, c] = line․split(' ')․map(Number);
if ((a + b) % 3 === 0 || (b + c) % 3 === 0 || (a + c) % 3 === 0) {
console․log("да");
} else {
console․log("нет");
}
rl․close;
}); ���� Тестирование граничных случаев
При сдаче задачи на автоматическую проверку (Codeforces, AtCoder, Acmp, Informatics и др․) важно проверить крайние значения:
- Все нули:
0 0 0→ да (0+0=0 делится на 3)․ - Максимальные цифры:
9 9 9→ да (9+9=18)․ - Смешанные остатки (1, 1, 1):
1 4 7→ нет (1+1=2, не делится на 3)․ - Смешанные остатки (2, 2, 2):
2 5 8→ нет (2+2=4, не делится на 3)․ - Классический «да» через 1 и 2:
1 2 0→ да (1+2=3)․ - Классический «да» через два нуля:
3 6 1→ да (3+6=9)․
��� Оценка сложности
- Временная сложность: O(1)․ Выполняется фиксированное количество арифметических операций (3 сложения, 3 взятия остатка или 3 инкремента счетчиков)․
- Память: O(1)․ Используется константное количество переменных (3-4 целых числа)․
Оба подхода (прямая проверка сумм и подсчет остатков) идеально укладываются в любые ограничения по времени (обычно 1-2 секунды) и памяти (256-512 МБ)․
���� Типичные ошибки и советы
- Чтение ввода: Если числа даны в одной строке через пробел, используйте
split(Python/JS) или последовательныйcin >> a >> b >> c(C++)․ Если каждое число на новой строке, эти же методы сработают корректно․ - Тип данных: Цифры от 0 до 9 идеально помещаются в
int(32 бита)․ Переполнение невозможно․ - Логическая ошибка: Проверка
(a+b+c) % 3 == 0— это другая задача (делится ли само число на 3)․ Нам нужно именно попарное сложение․
Задача «Вася любит математику и верит в приметы» — это отличная разминочная задача для начинающих программистов; Она тренирует:
- Базовый ввод/вывод․
- Работу с оператором остатка от деления (
%)․ - Написание составных логических условий (
||,&&)․ - Умение переводить словесное условие в формальный алгоритм․
Главный вывод: Для решения достаточно проверить три попарные суммы напрямую․ Это самый понятный, надежный и достаточно быстрый способ․ Анализ через остатки (подсчет cnt0, cnt1, cnt2) полезен для понимания математической структуры задачи и может пригодиться в более сложных вариациях (например, если цифр не 3, а N)․
Удачной отправки решения! ���