23.7.28 杭电暑期多校4部分题解

H - Merge the squares

题目大意

有一张用 n ∗ n n*n nn 个小正方形组成的图你需要用更大正方形去反复覆盖,每次需要恰好覆盖 2 2 2 50 50 50 个正方形,问如何操作才能使图变成一个 n ∗ n n*n nn 的正方形

解题思路

n ≤ 7 n\le7 n7 时显然直接覆盖就行

n > 7 n>7 n>7 时考虑递归

n n n 为偶数时可以分成四个 n 2 ∗ n 2 \frac{n}{2}*\frac{n}{2} 2n2n 的正方形做就可以了

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 aa, bb, ab 的矩形

然后处理无法保证每次只覆盖 50 50 50 个以内的小正方形就挂了

赛后发现可以去枚举 a a a,然后用辗转相除去计算 a ∗ b a*b ab 的矩形需要几个正方形,如果整张图可以小于 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;
}

你可能感兴趣的:(题解,数学)