Редакция для Мощение площади


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Автор: montes332

1. Идея

Нужно покрыть прямоугольник n x m квадратными плитками a x a.

Так как плитки можно выкладывать с выходом за границы площади, нам не нужно точно "вписывать" их внутрь. Достаточно понять:

  • сколько плиток нужно по длине n,
  • сколько плиток нужно по ширине m.

Если по одной стороне требуется x плиток, а по другой y, то всего понадобится x * y плиток.

Главная задача — правильно посчитать x и y, то есть округлить деление вверх.


2. Наблюдения

Наблюдение 1

Если длина стороны равна n, а сторона плитки равна a, то количество плиток по этой стороне равно:

  • n / a, если n делится на a без остатка;
  • иначе на одну больше.

Например:

  • для n = 8, a = 4 нужно 2 плитки;
  • для n = 9, a = 4 нужно 3 плитки.

Это и есть округление вверх от n / a.

Наблюдение 2

Округление вверх для целых чисел удобно считать формулой:

(n + a - 1) / a

в C++ для целочисленного деления, или

(n + a - 1) // a

в Python.

Наблюдение 3

Ответ может быть большим.

Например, если n = m = 10^9 и a = 1, то ответ равен 10^18.

Поэтому в C++ нужно использовать тип long long.


3. Алгоритм

  1. Считать n, m, a.
  2. Посчитать количество плиток по первой стороне:
    • x = (n + a - 1) / a
  3. Посчитать количество плиток по второй стороне:
    • y = (m + a - 1) / a
  4. Вывести x * y.

4. Почему это работает

Рассмотрим одну сторону длины n.

Одна плитка закрывает a метров этой стороны.
Две плитки закрывают 2 * a,
три — 3 * a, и так далее.

Нужно найти минимальное число плиток x, для которого:

x * a >= n

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

Минимальное такое x — это как раз округление вверх от n / a.

Аналогично для второй стороны получаем y.

После этого прямоугольник покрывается сеткой из x плиток по горизонтали и y плиток по вертикали. Всего таких плиток:

x * y

Меньше взять нельзя, потому что хотя бы по каждой стороне нужно не меньше x и y плиток соответственно.

Значит, найденное количество минимально.


5. Сложность

Алгоритм выполняет несколько арифметических операций.

  • Время: O(1)
  • Память: O(1)

6. Код на C++17

#include <iostream>
using namespace std;

int main() {
    long long n, m, a;
    cin >> n >> m >> a;

    long long x = (n + a - 1) / a;
    long long y = (m + a - 1) / a;

    cout << x * y << '\n';
    return 0;
}

7. Код на Python 3

n, m, a = map(int, input().split())

x = (n + a - 1) // a
y = (m + a - 1) // a

print(x * y)

Комментарии

Еще нет ни одного комментария.