考虑使用 while 循环求解。
理解题目
题目的意思是让我们按照“每一次都切出最大正方形”的切法来切蛋糕。输出最后能切出多少个蛋糕。
做法介绍
先输入进来 \(n\) 和 \(m\)。可以发现,如果 \(n\) 和 \(m\) 相等,那么说明这本身就是一个正方形。所以,输出 \(1\) 即可。
我捏了一个样例,如下图所示:

因为这个 \(5 \times 5\) 的正方形是当前最大的,所以只会有 \(1\) 个正方形。答案为 \(1\)。
此部分代码:
if(N==M) return 1;//已经是正方形,只有这 1 个。
Q:如果本身它不是正方形呢?这种情况怎么办?
A:其实,每一个长方形都会被切成若干个正方形。以样例说明为例。如下:
过程为:\(18 \times 5\),\(13 \times 5\),\(8 \times 5\),\(3 \times 5\),\(3 \times 2\),\(1 \times 2\),\(1 \times 1\)。所以得到三个 \(5 \times 5\) 正方形,两个 \(2 \times 2\) 正方形,两个 \(1 \times 1\) 正方形,总共 \(7\) 块。
我们来列一张表看一下。
| 步数 | 蛋糕大小 | 将切出的正方形大小 |
|---|---|---|
| \(0\) | \(18 \times 5\) | 切 \(5 \times 5\) |
| \(1\) | \(13 \times 5\) | ^ |
| \(2\) | \(8 \times 5\) | ^ |
| \(3\) | \(3 \times 5\) | 切 \(3 \times 3\) |
| \(4\) | \(3 \times 2\) | 切 \(2 \times 2\) |
| \(5\) | \(1 \times 2\) | 切 \(1 \times 1\) |
| \(6\) | \(1 \times 1\) | ^ |
不难发现,每个情况都会变成一个正方形,因为蛋糕本身就可以被看做 \(n \times m\) 个 \(1 \times 1\) 的小正方形。所以一定有解。
小优化
由上面的表格可以看出,有一些情况会切出相同的蛋糕。如果一个一个减的话,效率不太高。如果使用取模运算的话,会快一点。答案从加 \(1\) 就变成了加当前能切出同样大小的蛋糕的数量。
举例:
cnt+=(N/t);//N / t 表示现在能切几个一样大的蛋糕。
N=N%t;//切完后 N 的长度。
比如说,上表可以从第 \(0\) 步跳到第 \(3\) 步。减少运算次数。
AC 记录
AC 代码
#include<bits/stdc++.h>
using namespace std;
int count_square_cakes(int N,int M){
int cnt=0;
if(N==M) return 1;//已经是正方形,只有这 1 个。
while(N>=1&&M>=1){//如果行或列为 0,说明蛋糕已经没了。
if(N==M){
return cnt+1;//剩下的已经是一个正方形,cnt 指这个状态之前的答案,1 指剩下这个正方形。
}
int t=min(N,M);//最大的正方形的边长看的是长和宽中较小的那一条。
if(N>=M){
cnt+=(N/t);//N / t 表示现在能切几个一样大的蛋糕。
N=N%t;//切完后 N 的长度。
}else{
cnt+=(M/t);//M / t 表示现在能切几个一样大的蛋糕。
M=M%t;//切完后 M 的长度。
}
}
return cnt;//返回需要切出的正方形个数。
}
浙公网安备 33010602011771号