题目来源:统计方形(数据加强版) - 洛谷
参考书籍:《深入浅出程序设计竞赛(基础篇)》
解题思路:这道理适合用暴力枚举求解。我把书上提到的四种枚举方法分享给大家。
解题1:减少枚举量
以某个坐标为顶点,统计其正方形和长方形。
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
int main()
{
LL n, m,squ = 0,rec = 0;
cin >> n >> m;
for (LL x = 0; x <= n; x++)
{
for (LL y = 0; y <= m; y++)
{
LL tmp = min(x, y) + min(y, n - x) + min(n - x, m - y) + min(m - y, x);
squ += tmp;
rec += n * m - tmp; //长方形
}
}
printf("%lld %lld", squ / 4, rec / 4);
return 0;
}
解题2 :去掉重复情况,只枚举方形的右下角顶点。
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
int main()
{
LL n, m, squ = 0, rec = 0;
cin >> n >> m;
for (LL x = 0; x <= n; x++)
{
for (LL y = 0; y <= m; y++)
{
LL tmp = min(x, y);
squ += tmp;
rec += x * y - tmp; //长方形
}
}
printf("%lld %lld", squ , rec);
return 0;
}
解题3:枚举其他要素。枚举方形的边长,其实就是统计n ✖m的大矩形中包含多少个边长为a ✖b的小矩形。答案:(n - a + 1) *(m - b +1)
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
int main()
{
LL n, m, squ = 0, rec = 0;
cin >> n >> m;
for (LL x = 1; x <= n; x++)
{
for (LL y = 1; y <= m; y++)
{
if (x == y)
{
squ += (n - x + 1) * (m - y + 1);//正方形
}
else
{
rec += (n - x + 1) * (m - y + 1);//长方形
}
}
}
printf("%lld %lld", squ, rec);
return 0;
}
解题 4 :减少枚举量
在这个问题中,我们需要确定一个 n ✖m 方格的矩形包含多少个正方形和长方形(不包含正方形)。为了计算这个,我们可以用以下方法:
-
计算正方形的数量:
- 对于一个 n ✖m 的矩形,最小的正方形是 1×1 的方格,然后是 2×2,直到 min(n,m)×min(n,m)。
- 所以,1×1 的正方形有 n×m 个。
- 2×2 的正方形有 (n−1)×(m−1) 个,以此类推。
- 总正方形的数量是
2 .计算长方形的数量:
在一个 n×m 的矩形上,计算所有可能的长方形(包括正方形)的数量,可以通过计算所有可能的顶点对来完成。每个长方形由其对角线上的两个顶点唯一确定。要形成一个长方形,我们需要选择两个不同的水平坐标和两个不同的垂直坐标。
-
选择水平坐标:在长度为 n 的矩形,有 n+1 个水平的格线。从这n+1 个格线中选择两个不同的格线作为长方形的上下边界,可以有 C(n+1,2) 种选择方法,这是因为顶点对的选择是组合而不是排列(顺序不重要)。
-
选择垂直坐标:同理,在宽度为 m 的矩形,有m+1 个垂直的格线。选择两个不同的垂直格线作为长方形的左右边界,可以有 C(m+1,2) 种选择方法。
-
计算组合:要形成一个长方形,我们需要同时选择水平和垂直坐标,所以这两种选择的组合数是乘积形式的:C(n+1,2)×C(m+1,2)。
-
化简组合公式:组合公式 C(x,2)=x(x−1) /2可以应用于这两个选择,所以总的可能的长方形数量是:
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
int main()
{
LL n, m, squ = 0, rec = 0;
cin >> n >> m;
for (LL x = 1; x <= min(n,m); x++)
{
squ += (n - x + 1) * (m - x + 1) ;//正方形
}
rec = n * m* (n + 1) * (m+ 1) /4 - squ ;//长方形
printf("%lld %lld", squ, rec);
return 0;
}