先用公式统计所有矩形,再枚举边长统计正方形,二者相减得到非正方形长方形。
OJ: luogu
题目 ID: P2241
难度:入门
标签:数学组合计数python
日期: 2026-07-15 21:30
题意
给定一个 n x m 的方格棋盘,统计其中包含多少个正方形,以及多少个长方形。这里“长方形”不包含正方形。
思路
先统计正方形。
如果正方形边长为 side,它的左上角有:
text
(n - side + 1) * (m - side + 1)种放法。枚举 1..min(n,m) 的所有边长并求和,就是正方形总数。
再统计所有矩形。一个矩形由两条横向网格线和两条纵向网格线决定:
text
C(n + 1, 2) * C(m + 1, 2)
= n * (n + 1) * m * (m + 1) // 4所有矩形数量减去正方形数量,就是题目要求的非正方形长方形数量。
Python 知识
- Python 的
int是任意精度整数,不用担心这里的计数超过 C++int。 //是整数除法,适合写组合计数公式。range(1, min(n, m) + 1)用来枚举所有可能的正方形边长。
参考笔记:
/home/rainboy/mycode/hugo-blog/content/program_language/python/math_tools.md/home/rainboy/mycode/hugo-blog/content/program_language/python/input_output_and_strings.md
代码
python
n, m = map(int, input().split())
square_count = 0
for side in range(1, min(n, m) + 1):
square_count += (n - side + 1) * (m - side + 1)
all_rectangles = n * (n + 1) * m * (m + 1) // 4
rectangle_count = all_rectangles - square_count
print(square_count, rectangle_count)cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-07-27 00:00
* update_at: 2026-07-27 00:00
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, m;
int main() {
cin >> n >> m;
ll sq = 0;
for (ll side = 1; side <= min(n, m); side++)
sq += (n - side + 1) * (m - side + 1);
ll all = n * (n + 1) * m * (m + 1) / 4;
ll rect = all - sq;
cout << sq << " " << rect << endl;
return 0;
}Pythonic 写法
sum 推导数正方形:
python
n, m = map(int, input().split())
squares = sum((n - s + 1) * (m - s + 1) for s in range(1, min(n, m) + 1))
print(squares, n * (n + 1) * m * (m + 1) // 4 - squares)复杂度
时间复杂度为
总结
方格计数题要优先想“选边界”。所有矩形用选两条横线和两条竖线统计,正方形再按边长单独统计。