题解:CF980B Marlin

· · 题解

首先我们不难观察到一个性质:构造上下对称或左右对称的局面是一定正确的。证明也不难,对于上下,每条从 (1,1) 到 (4,n) 的路径都可以上下翻转一下变成从 (4,1) 到 (1,n) 的路径,两种路径是一一对应的,所以数量相同。左右基本同理。

所以接下来就好构造了。

光这样说比较难理解,下面举三个对应的例子来直观感受一下,假设样例的 4\times7 网格:

.......
.##....
.##....
.......
.......
..###..
.......
.......
.......
.#####.
.#...#.
.......

所以这道题实际上不可能输出 No(题目也保证了 k 的范围),骗你的。

码风比较猎奇,可以结合上面的例子食用,手模一下好理解一些。

cout << "Yes\n";
for(int i = 1; i <= n; i++) cout << '.'; cout << '\n';
if(k & 1) {
    if(k <= n - 2) {
        for(int i = 1; i <= (n - k) / 2; i++) cout << '.';
        for(int i = 1; i <= k; i++) cout << '#';
        for(int i = 1; i <= (n - k) / 2; i++) cout << '.'; cout << '\n';
        for(int i = 1; i <= n; i++) cout << '.'; cout << '\n';
    } else {
        cout << '.';
        for(int i = 1; i <= n - 2; i++) cout << '#';
        cout << '.' << '\n' << '.';
        for(int i = 1; i <= (k - n + 2) / 2; i++) cout << '#';
        for(int i = 1; i <= n - (k - n + 2) - 2; i++) cout << '.';
        for(int i = 1; i <= (k - n + 2) / 2; i++) cout << '#'; cout << '.' << '\n';
    }
} else {
    for(int i = 1; i <= 2; i++) {
        cout << '.';
        for(int j = 1; j <= k / 2; j++) cout << '#';
        for(int j = 1; j <= n - k / 2 - 1; j++) cout << '.';
        cout << '\n'; 
    }
}
for(int i = 1; i <= n; i++) cout << '.';