跳到主要内容
原文194 词数1 分钟

题解:P15421 像你这样的朋友

概述

在 n 乘 n 的 01 网格里尽量多填 1,要求任取一个 1 上下左右移动一步后都不出现横向或纵向连续三个 1,填 n 方除以 3 上取整个可拿基础分。做法是按 (i+j) 除以 3 的余数把格子分成三个集合,同一集合内连续三格至多一个 1,任填一个集合都合法,由鸽巢原理最大集合的大小恰为 n 方除以 3 上取整。代码直接打表输出各 n 的构造。

题意简述​

在 n×nn\times n 的 01\texttt{01} 网格中尽可能多填入 1\texttt{1},使得选取任意一个 1\texttt{1} 上下左右移动一步后,都不会出现横向或纵向连续 33 个 1\texttt{1}。

填入 ⌈n23⌉\left\lceil\frac{n^2}{3}\right\rceil 个 1\texttt{1} 可以获得 100100 分基础分,超出部分可以获得附加分。

解题思路​

我们可以将每个格子 (i,j)(i,j) 按照 (i+j) mod 3={ 0,1,2 }(i+j)\bmod 3=\set{0,1,2} 划分为 33 个集合。显然在每个集合内,连续 33 个格子至多有 11 个 1\texttt{1},因此任意一个集合填入 1\texttt{1} 都满足条件。根据鸽巢原理,最大集合的大小为 ⌈n23⌉\left\lceil\frac{n^2}{3}\right\rceil,即可获得 100100 分基础分。

参考代码​

283 Bcpp
#include <bits/stdc++.h>
using namespace std;

int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
for(int n=1;n<=270;n++)
{
int t=(n+1)%3;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cout<<((i+j)%3==t?'x':'o');
}
cout<<'\n';
}
}
return 0;
}