CF1667C (Round #783) 题解 构造

  • 鸣谢:@SpadeA261

  • 挑战最短代码

  • (由于笔者太菜了不会画图,读者珂以利用方格纸辅助理解)


link

本题解主要讲解一种构造方式。

本文作如下定义:

  • \(n\) 阶棋盘”即为题意中 \(n\)\(n\) 列的棋盘;

  • 对角线(与主对角线平行)的编号为其上格子的行号减列号。


设答案为 \(k\),考虑在 \(n\) 阶棋盘左上角的 \(k\) 阶棋盘中不重行不重列地放置 \(k\) 个棋子,于是 \(n\) 阶棋盘中的前 \(k\) 行均能被同行棋子攻击,前 \(k\) 列均能被同列棋子攻击。

于是还剩下右下角的 \(n-k\) 阶棋盘,它们只能被同对角线的棋子攻击。

\(n-k\) 阶棋盘可被划分为 \(2(n-k)-1\) 条对角线,为使它们被覆盖,需要有 \(k\ge2(n-k)-1\)

解得 \(k=\left\lceil\dfrac{2n-1}{3}\right\rceil=\left\lfloor\dfrac{2n+1}{3}\right\rfloor\)

同时 \(n=\left\lfloor\dfrac{3k+1}{2}\right\rfloor\)

接下来考虑放置方案。

\(k\ge2(n-k)-1\) 变形得 \(\left\lfloor\dfrac{k+1}{2}\right\rfloor\ge n-k\),注意到 \(n-k\) 即为 \(n-k\) 阶棋盘中编号非负的对角线数量。

考虑用 \(k\) 阶棋盘中的前 \(\left\lfloor\dfrac{k+1}{2}\right\rfloor\) 列上的棋子攻击这些对角线。

首先在 \((1,1)\) 放置一枚棋子别问为什么问就是看上去很优,则它能攻击 \(0\) 号对角线;

接着采用类似“马走日”的方法,下一枚棋子放置在上一枚棋子位置行号 \(+2\),列号 \(+1\) 的位置,于是它能攻击的对角线编号 \(+1\)

也就是像 \((3,2),(5,3)…\) 这样,依次攻击 \(n-k\) 阶棋盘中的非负对角线,直到第 \(\left\lfloor\dfrac{k+1}{2}\right\rfloor\) 列,此时棋子刚好没有超出 \(k\) 阶棋盘,同时编号非负的对角线全部被攻击到。

剩下的任务就是用 \(k\) 阶棋盘余下的列上的棋子攻击 \(n-k\) 阶棋盘余下的对角线。

\(k\) 阶棋盘中,考虑再下一列上的棋子,由于奇数行已全被占据,棋子应被放在偶数行,我们将它放在第二行,也就是放在 \((2,\left\lfloor\dfrac{k+1}{2}\right\rfloor+1)\)

它能攻击的对角线,编号为 \(2-(\left\lfloor\dfrac{k+1}{2}\right\rfloor+1)=-\left\lfloor\dfrac{k-1}{2}\right\rfloor\)

\(n-k\) 阶棋盘中编号最小的对角线,编号为 \(1-(n-k)=1-\left\lfloor\dfrac{3k+1}{2}\right\rfloor+k=-\left\lfloor\dfrac{k-1}{2}\right\rfloor\)

于是这枚棋子刚好攻击到编号最小的对角线。

我们依旧采用上面提到的“马走日”的方法放置棋子,于是第 \(k\) 列的棋子位置是 \((2\left\lfloor\dfrac{k}{2}\right\rfloor,k)\),显然它攻击的对角线编号不是 \(0\) 就是 \(-1\),此时编号为负的对角线也全部被攻击到。

至此我们完成了全部分析。

在代码实现中,我们可以枚举列号,按上面的方法模拟行号的变化。

代码很短,在 \(0.2kb\) 以内传说中思维很巧妙代码很好写的题

#include<cstdio>
int n,k;
int main(){
	scanf("%d",&n);
	k=(n*2+1)/3;
	printf("%d",k);
	for(int i=1,x=-1;i<=k;++i){
		if((x+=2)>k) x=2;
		printf("\n%d %d",x,i);
	}
	return 0;
}
posted @ 2022-04-20 18:34  XG0000  阅读(154)  评论(0)    收藏  举报