1.题目
设有一个 N × M N \times M N×M方格的棋盘 ( 1 ≤ N ≤ 100 , 1 ≤ M ≤ 100 ) (1≤N≤100,1≤M≤100) (1≤N≤100,1≤M≤100)
求出该棋盘中包含有多少个正方形、多少个长方形(不包括正方形)。
例如:当 N = 2 , M = 3 N=2, M=3 N=2,M=3时:
正方形的个数有 8 8 8个:即边长为 1 1 1的正方形有 6 6 6个;
边长为 2 2 2的正方形有 2 2 2个。
长方形的个数有 10 10 10个:
即
2 × 1 2 \times 1 2×1的长方形有 4 4 4个
1 × 2 1 \times 2 1×2的长方形有 3 3 3个:
3 × 1 3 \times 1 3×1的长方形有 2 2 2个:
3 × 2 3 \times 2 3×2的长方形有 1 1 1个:
如上例:输入: 2 , 3 2,3 2,3
输出: 8 , 10 8,10 8,10
输入格式
N , M N,M N,M
输出格式
正方形的个数与长方形的个数
样例 #1
样例输入 #1
2 3
样例输出 #1
8 10
【题目来源】
NOIP 1997 普及组第一题
2.分析
方法:1.暴力枚举 2.公式推导
3.代码
1.暴力枚举(时间复杂度极高)
直接枚举左上角和右下角坐标,判断长宽是否相等即可
2.公式法
利用求解 不同长度的线段的个数 ,以及考虑如何组合,求出正方形、长方形个数
#include <iostream>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
int z = 0;
//1.先求正方形个数
//分别从长、宽为n、m(或者m、n)中选取长度为 1,2,...min(n,m)的线段
//长为 n 中 长度为1 , 2 ....n 线段的个数分别为 n , n-1 ....1
//宽为 m 中 长度为1 , 2 ....m 线段的个数分别为 m , m-1 ....1
//正方形个数即为 线段长度相同的线段个数分别对应相乘 n*m (n-1)*(m-1) .....直到m或n中有一个为0
for (int i = n, j = m; i > 0 && j > 0; --i, --j) { //保证最多加到 以较短边为边长的 正方形
z += i * j;
}
//2.再求正方形和长方形的个数和
//利用上面的分析,总数 即为 长宽情况和 相乘 即 [(1+n)*n/2] * [(1+m)*m/2]
int z_c = (1 + n) * (1 + m) * n * m / 4; //[最大为1e8不会爆int]
cout << z << ' ' << z_c - z;
return 0;
}
4.总结
公式推导能力
5.更新日志
2022.7.22
欢迎交流、讨论、指正~
不正确、不理解之处欢迎评论留言~