把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【BZOJ2940】[POI2000] 条纹(Multi-SG)

点此看题面

大致题意: 有一堆石子,每次可以取\(a\)\(b\)\(c\)个石子,并把剩下的石子分成两部分。每次询问给定石子数目\(n\),问先手是否有必胜策略。

\(Multi-SG\)

听起来很高级的东西,其实也就一般般啦。

放在这题中,我们和普通题目一样定义\(SG\)函数,假设当前有完整一堆\(i\)个石子,考虑其后继状态。

我们枚举取几个石子(\(a\)\(b\)\(c\)),然后枚举怎么分,就得出了所有后继状态。

\(SG(i)\)的值就等于:

\[mex\{SG(j)\ xor\ SG(i-j-a),SG(j)\ xor\ SG(i-j-b),SG(j)\ xor\ SG(i-j-c)\} \]

因为\(a,b,c\)是一开始就给定的,因此我们完全可以预处理。

最后只要对于每个询问的\(n\)判断\(SG(n)\)是否为\(0\)即可。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 1000
using namespace std;
int n,a,b,c,SG[N+5],vis[N+5];
int main()
{
	RI Tt,i,j;for(scanf("%d%d%d",&a,&b,&c),i=1;i<=N;++i)//预处理i的SG值
	{
		for(j=0;j+a<=i;++j) vis[SG[j]^SG[i-j-a]]=i;//取a个石头
		for(j=0;j+b<=i;++j) vis[SG[j]^SG[i-j-b]]=i;//取b个石头
		for(j=0;j+c<=i;++j) vis[SG[j]^SG[i-j-c]]=i;//取c个石头
		for(j=0;vis[j]==i;++j);SG[i]=j;//SG值
	}
	scanf("%d",&Tt);W(Tt--) scanf("%d",&n),puts(SG[n]?"1":"2");return 0;//直接判断
}
posted @ 2020-06-04 13:49  TheLostWeak  阅读(93)  评论(0编辑  收藏  举报