C++棋盘正方形与长方形计数:公式推导与代码实现
这个问题是经典的**棋盘计数问题**,用数学公式即可高效解决,无需模拟遍历(暴力枚举复杂度O(N²M²)也能过,因为N、M都≤100,但公式法是O(1))。 ## 🧮 核心数学原理 在 `N×M` 的网格中: - **正方形个数**: 遍历边长 `k`(从 1 到 `min(N, M)`),每个边长为 `k` 的正方形数量为 `(N - k + 1) × (M - k + 1)`,累加。 \[ \text{正方形总数} = \sum_{k=1}^{\min(N,M)} (N-k+1)(M-k+1) \] - **长方形(包括正方形)总个数**: 任意选择一个矩形,需要选两条水平线和两条竖直线。 在 `N` 条水平线中选 2 条:`C(N+1, 2) = N(N+1)/2` 在 `M` 条竖直线中选 2 条:`M(M+1)/2` 两者相乘得到**所有矩形(含正方形)总数**。 - **长方形(不包括正方形)个数**: 用总矩形数减去正方形数。 --- ## 💻 C++ 代码实现 ```cpp #include <iostream> using namespace std; int main() { int N, M; cin >> N >> M; // 计算正方形总数 long long squares = 0; int minNM = min(N, M); for (int k = 1; k <= minNM; ++k) { squares += (long long)(N - k + 1) * (M - k + 1); } // 计算所有矩形(含正方形)总数 long long totalRectangles = (long long)N * (N + 1) / 2 * M * (M + 1) / 2; // 长方形(不含正方形) long long rectangles = totalRectangles - squares; cout << squares << "," << rectangles << endl; return 0; } ``` --- ## 📊 代码解析 - **`minNM = min(N, M)`**:正方形最大边长不能超过棋盘短边。 - **循环累加**:每次计算边长为 `k` 的正方形数量,注意乘数都要转换为 `long long`,避免 `int` 溢出(N、M最大100,直接算也安全,但用 `long long` 更稳健)。 - **总矩形公式**: `N * (N+1) / 2` 表示在 N 行网格中选上下两条水平线的组合数,`M` 同理。两者乘积即为所有矩形数。 - **最终输出**:`squares` 和 `rectangles` 用逗号分隔,与题目输出格式一致。 --- ## ⚠️ 注意事项 1. **数据类型**:虽然本题 N、M ≤ 100,最大结果在 10^8 量级,`int` 可能勉强放下,但推荐用 `long long` 防止边界情况。 2. **输入格式**:题目示例用逗号分隔输入(`3,2`),但实际 OJ 通常用空格或换行,**建议直接用 `cin >> N >> M`**,它天然支持空格/换行,也能支持逗号?——不,逗号会读取失败。保险起见,如果输入是逗号,需要特殊处理。但绝大多数 OJ 用空格。 3. **公式正确性**:这是经典的排列组合计数,务必记住“选线”思想,而不是模拟每个格子。 --- ## 🔧 扩展思考 - **如果棋盘是带障碍的**,就不能用公式,需要动态规划或扫描线法。 - **如果只问正方形**,上述循环是标准解法,也可以直接公式求和。 - **如果 N 和 M 特别大(>10^7)**,循环依然适用,但注意结果可能要用大数(如 `__int128` 或高精度)。 --- ## 📚 推荐的学习资源 - [组合计数基础(OI Wiki)](https://oi-wiki.org/math/combinatorics/) - [LeetCode 221. 最大正方形](https://leetcode.cn/problems/maximal-square/)(动态规划版正方形计数) - 《算法竞赛入门经典》第二版,组合数学章节 ######[AI写代码神器 | 989点数解答 | 2026-08-28 20:46:25]
- 棋盘方格中正方形与长方形数量的计算方法(字节豆包 | 460点数解答 | 2026-04-20 12:14:43)78
- Python 实现球类:精准计算半径、表面积与体积,附输入验证与异常处理!(阿里通义 | 261点数解答 | 2024-11-28 21:19:39)571
- 解决 consoleapplication40.cpp 中 buildtree 模板参数推导失败错误的方法(字节豆包 | 138点数解答 | 2024-11-10 23:42:06)288
- Pascal 实现:输出数字组成的 n*n 正方形及代码详解(字节豆包 | 443点数解答 | 2025-12-07 17:08:31)93
- C语言实现:输出第i列由数字i组成的n*n正方形及详细解析(字节豆包 | 344点数解答 | 2025-12-07 17:09:34)109
- Python:根据输入边长生成数字组成的正方形图案(字节豆包 | 216点数解答 | 2025-12-13 21:33:12)96
- Python实现生成第i列由数字i组成的n×n正方形及代码详解(字节豆包 | 230点数解答 | 2025-12-13 21:33:47)111
- Python 破解:计算 n*n 网格中只含 1 的最大矩形数字和! (字节豆包 | 534点数解答 | 2026-02-07 20:24:57)83
- C++ 单调栈统计无障碍矩形数量(P3345)(DeepSeek | 1687点数解答 | 2026-06-14 19:52:20)58
- 单调栈算法修正:矩形计数问题详解(DeepSeek | 988点数解答 | 2026-06-14 19:58:27)53
- Java 实现:从点类到圆类,计算圆心坐标(50,30)、半径 4 的圆周长与面积(字节豆包 | 246点数解答 | 2024-11-11 16:36:30)439
- 51 单片机:定时器 0 实现 8 个 LED 循环点亮,附代码及优化建议(字节豆包 | 1193点数解答 | 2024-12-27 15:10:29)483