1. 问题分析与算法选择
这道题目要求我们计算一个n×m的棋盘上所有正方形和长方形(不包括正方形)的数量。初看这个问题,很多人的第一反应可能是暴力枚举所有可能的矩形,然后判断其是否为正方形。但这种方法的时间复杂度高达O(n²m²),对于n和m达到5000的情况显然不可行。
实际上,这个问题可以通过数学推导来优化。我们需要分别计算正方形和长方形的数量:
- 正方形数量:对于边长为k的正方形,在n×m棋盘上可以放置(n-k+1)×(m-k+1)个
- 矩形总数:对于长宽为i×j的矩形,可以放置(n-i+1)×(m-j+1)个
- 长方形数量:矩形总数减去正方形数量
这种数学方法将时间复杂度降低到了O(min(n,m))(计算正方形)和O(nm)(计算矩形总数),对于n,m≤5000的情况完全可行。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数学推导与公式证明
2.1 正方形数量计算
对于一个k×k的正方形,在n×m棋盘上的摆放方式数量为:
code复制(n-k+1) × (m-k+1)
这是因为:
- 行方向有(n-k+1)种选择(从第1行到第n-k+1行开始)
- 列方向有(m-k+1)种选择(从第1列到第m-k+1列开始)
因此,总正方形数量为:
code复制sum_{k=1}^{min(n,m)} (n-k+1)(m-k+1)
2.2 矩形总数计算
对于任意i×j的矩形(i≤n, j≤m),在棋盘上的摆放方式数量为:
code复制(n-i+1) × (m-j+1)
因此,所有矩形(包括正方形)的总数为:
code复制sum_{i=1}^n sum_{j=1}^m (n-i+1)(m-j+1)
这个双重求和可以简化为:
code复制[sum_{i=1}^n (n-i+1)] × [sum_{j=1}^m (m-j+1)] = [n(n+1)/2] × [m(m+1)/2]
2.3 长方形数量计算
长方形数量就是矩形总数减去正方形数量:
code复制长方形数量 = 矩形总数 - 正方形数量
3. 算法实现与优化
3.1 基础实现
根据上述数学推导,我们可以直接实现算法:
cpp复制#include <iostream>
#include <algorithm>
using namespace
