Skip to content

喵~ 各位解题的小伙伴们好呀!今天本喵要给大家带来一道超级经典的入门题,Codeforces 1A - Theatre Square!别看它只是第一题,里面可是藏着一些小小的陷阱哦~ 让我们一起来看看吧!

题目大意

题目是这样的:在一个 n x m 米的矩形广场上,我们要用 a x a 米的正方形石板来铺满它。石板不能打碎,而且必须和广场的边平行放置。我们可以铺设比广场大的区域,但整个广场必须被完全覆盖。问我们最少需要多少块石板呢?

简单来说,就是用大的正方形去盖住一个大的长方形,问最少要用多少个正方形,喵~

举个例子,如果广场是 6 x 6 米,石板是 4 x 4 米。

  • 在长度为 6 的边上,铺一块 4 米的石板不够,所以需要 2 块。
  • 在宽度为 6 的边上,同样需要 2 块。
  • 这样就像一个 2x2 的田字格一样,总共需要 2 * 2 = 4 块石板。

Theatre Square Example

题解方法

这个问题呀,我们可以把它拆开来看。二维的问题不好想,我们就先把它简化成一维的嘛!

想象一下,我们有一条长为 n 米的线段,要用长度为 a 米的小木棍去覆盖它。需要多少根小木棍呢?

比如说,n=6, a=4。我们铺第一根木棍,覆盖了4米,还剩下2米没有覆盖。因为木棍不能掰断,所以我们必须再用一根完整的木棍来覆盖剩下的2米。所以一共需要 1+1=2 根木棍,对吧?

这其实就是一个经典的 向上取整 问题!覆盖长度 n 需要的石板数量就是 n/a 向上取整。数学上记作 ceil(n/a)

那在程序里怎么计算向上取整呢?如果用浮点数 ceil() 函数,可能会有精度问题,而且速度也慢一些。对于正整数,我们有一个超好用的小技巧:(n + a - 1) / a。利用整型除法自动向下取整的特性,我们先给 n 加上 a-1,就巧妙地实现了向上取整的效果,是不是很神奇喵?

好啦,一维的问题解决了,二维的就简单啦!

  • 长为 n 的边需要的石板数量是:(n + a - 1) / a
  • 宽为 m 的边需要的石板数量是:(m + a - 1) / a

把它们乘起来,不就是总共需要的石板数量了嘛!

所以,最终的公式就是:((n + a - 1) / a) * ((m + a - 1) / a)

但是!还有一个小陷阱! 题目里说 n, m, a 最大可以到 10^9。那我们算出来的石板数量可能会非常非常大,10^9 * 10^9 = 10^18 呢!普通的 int 类型可存不下这么大的数字,会 溢出 的。所以,我们必须使用 long long 类型来存储变量和计算结果,这样才不会出错哦!

题解

下面就是本喵为大家准备的 C++ 代码啦,加上了详细的注释,方便大家理解喵~

cpp
#include <iostream>

// 主函数入口喵~
int main() {
    // 为了让输入输出快一点,加上这两行是个好习惯哦
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);

    // 题目给的 n, m, a 可能会很大,结果的乘积会更大
    // 所以必须使用 long long 来防止数据溢出!这很重要!
    long long n, m, a;
    
    // 从标准输入读取广场的长、宽和石板的边长
    std::cin >> n >> m >> a;

    // 计算长度为 n 的边需要多少块石板
    // 这里使用了 (n + a - 1) / a 的技巧来向上取整
    // 比如 n=6, a=4, (6 + 4 - 1) / 4 = 9 / 4 = 2 (整型除法)
    long long num_stones_n = (n + a - 1) / a;

    // 计算宽度为 m 的边需要多少块石板,方法同上
    long long num_stones_m = (m + a - 1) / a;

    // 总石板数就是两边所需石板数的乘积
    long long total_stones = num_stones_n * num_stones_m;

    // 把最终结果打印出来
    std::cout << total_stones << std::endl;

    return 0; // 程序正常结束啦
}

知识点介绍

这道题虽然简单,但涉及到的两个知识点在算法竞赛中非常重要哦,一定要掌握好!

  1. 向上取整 (Ceiling Division)

    • 向上取整的意思是,一个数除以另一个数,结果要取不小于它的最小整数。比如 ceil(6 / 4) = ceil(1.5) = 2
    • 在编程中,特别是处理整数时,我们常用 (被除数 + 除数 - 1) / 除数 这个公式来计算。也就是 (x + y - 1) / y 来计算 ceil(x/y)。这个公式避免了浮点数运算,既快速又精确,是每个ACMer的必备小技巧!
  2. 数据溢出 (Integer Overflow)

    • 计算机里存储数字的变量是有范围的。比如在C++里,int 类型通常是32位的,大概能表示到 2 * 10^9。而 long long 是64位的,可以表示到 9 * 10^18 左右,范围大得多!
    • 当计算结果超出了变量类型能表示的最大范围时,就会发生“溢出”。溢出的结果通常是一个奇怪的、不正确的值。就像一个小杯子装不下大桶的水一样,水会洒出来的喵~
    • 所以,在做题时一定要先看数据范围,估算一下结果可能会有多大,然后选择一个足够大的数据类型。这是避免 WA(Wrong Answer)的一个好习惯!

好啦,今天的题解就到这里啦!是不是很简单呢?只要注意向上取整和数据溢出这两个点,就能轻松AC啦!希望能帮到大家,我们下次再见喵~

Released under the MIT License.