题目大意
有一张用 n ∗ n n*n n∗n 个小正方形组成的图你需要用更大正方形去反复覆盖,每次需要恰好覆盖 2 2 2 到 50 50 50 个正方形,问如何操作才能使图变成一个 n ∗ n n*n n∗n 的正方形
解题思路
当 n ≤ 7 n\le7 n≤7 时显然直接覆盖就行
n > 7 n>7 n>7 时考虑递归
当 n n n 为偶数时可以分成四个 n 2 ∗ n 2 \frac{n}{2}*\frac{n}{2} 2n∗2n 的正方形做就可以了
当 n n n 为奇数时,我在考场上只想着把边分成 a + b a+b a+b,使 a = b + 1 a=b+1 a=b+1,然后处理 a ∗ a , b ∗ b , a ∗ b a*a,\space b*b,\space a*b a∗a, b∗b, a∗b 的矩形
然后处理无法保证每次只覆盖 50 50 50 个以内的小正方形就挂了
赛后发现可以去枚举 a a a,然后用辗转相除去计算 a ∗ b a*b a∗b 的矩形需要几个正方形,如果整张图可以小于 50 50 50 便去递归
时间复杂度最差为 O ( n 2 ) O(n^2) O(n2)
code
#include
using namespace std;
const int N = 1e6 + 9;
struct lol {int x, y, r;} e[N];
int n, m;
int gg(int a, int b) {return b ? a / b + gg(b, a % b) : 0;}
void dfs(int x, int y, int r, int c) {
if (r == 1 || c == 1) return;
if (r != c) {
if (r < c) {
dfs(x, y, r, r);
dfs(x, y + r, r, c - r);
} else {
dfs(x, y, c, c);
dfs(x + c, y, r - c, c);
}
return;
}
e[++ m] = {x, y, r};
if (r <= 7) return;
int a, b;
for (int i = r / 2; i >= 2; -- i) {
int res = gg(i, r - i) * 2 + 2;
if (res <= 50) {a = i; b = r - i; break;}
}
dfs(x, y, a, a);
dfs(x + a, y + a, b, b);
dfs(x + a, y, b, a);
dfs(x, y + a, a, b);
}
int main() {
scanf("%d", &n);
dfs(1, 1, n, n);
printf("%d\n", m);
for (int i = m; i >= 1; -- i)
printf("%d %d %d\n", e[i].x, e[i].y, e[i].r);
return 0;
}