LOJ#551 Matrix

本地打表在线AC什么的最喜欢了。

题意

AliceBob在玩游戏,他们要给一个n×n的矩阵打标记。初始时没有任何标记,每一轮Bob先手,两个人可以选一个格子打上自己的标记(AliceA,BobB),但如果选择了已经打过标记的格子就输掉游戏。

如果在某个时刻,存在一个长度为n的排列p使得对于i=1,2,,n,有第i行第pi列的标记为A成立,那么Alice获胜。

如果在n22轮后,Alice依然没有获胜,那么Bob获胜。

给定T组询问,每次给定一个数n,问在之前的游戏规则下:

1、双方记得之前的所有操作,Alice是否有必胜策略。

2Alice只记得当前这一轮Bob的操作,Bob记得所有操作,Alice是否有必胜策略。

T100,n1018

题解

这种题目就应该大力猜结论。

先考虑比较简单的第一问,在n比较大的平凡情况下,假设Bob标记了第x行的某个格子,那么Alice就可以选择第x行的另一个格子(记为第y列)。之后,Alice选择第y列上的格子一定是不优的,因此对Alice来说,她可以将棋盘重新看作(n1)×(n1)大小的。只要在(n1)×(n1)时有必胜策略,那么n×n时就一定有必胜策略。

那么暴搜最小的有必胜策略的n,可以本地发现n=4时有必胜策略,因此第一问的答案就是[n4]

对于第二问,显然必胜策略应该避免选择已经标记过的格子。可以发现唯一的方法就是使棋盘上的格子两两匹配,对于每一个匹配,假如Bob选择了其中一个,那么Alice就立即选择另一个。

首先n为奇数的时候显然无解,考虑怎么在n为偶数的时候构造一种匹配方案,使得对于每一个匹配无论选择哪一个,总存在一个排列满足对应的位置都标记了A

先本地暴搜n小的情况(当然要加一点剪枝),可以发现n=4n=6都是有解的。

那么对于更大的n,只要在对角线上依次放上n=4n=6的,剩下的位置随便匹配即可。

比如下面就是n=10的构造方法,蓝色部分随意匹配即可。

栗子

于是第二问的答案就是[n4,n0(mod2)]

#include<cstdio>
#define int long long
signed main()
{
	int T,n;
	scanf("%lld",&T);
	while(T--)
	{
		scanf("%lld",&n);
		puts(n>=4?"Yes":"No");
		puts(n>=4&&!(n&1)?"Yes":"No");
	}
	return 0;
}