#C241112A. 石子游戏


#C241112A. 石子游戏

标签(Label)

  • 数学
  • 博弈论

网址(Website)

题目详情 - 石子游戏 - Super

题解 - 石子游戏 - Super

题目(Problem)

题解(Solution)

$\qquad$我c,我原来竟然想对了?但是好像代码写挂了。。。

$\qquad$。。。好吧,想挂了。

$\qquad$这道题对于分类讨论的能力考验非常好!!!

$\qquad$发现 $1$ 非常的特殊,直接开始枚举 $1$ 。容易枚举到一堆 1 和一个 $x$ 的情况。

出题者题解

算法分析

全 1 的话先手赢当且仅当 $n \mod 3 \neq 0$。

如果是一堆 1 和一个 $x$,先手可以选择把 $x$ 取干净,剩余 $n - 1$ 个 1,或把 $x$ 取到 1,剩余 $n$ 个 1。两种可能至少有一个会赢,因此一堆 1 和一个 $x$ 先手必胜。

假设初始有 $k (k > 1)$ 个数大于 1,后手需要尽量控制 $k \neq 1$。

若后手操作之前 $k = 2$,则后手有三种选择:把两个大于 1 的堆取到 1,把一个取到 1 另一个取干净,两个都取干净。三种选择恰好有一种获胜,因此后说操作前如果 $k = 2$,则后手必胜。

若后手操作之前 $k = 1$ 且唯一比 1 大的元素大于 2,则后手有三种选择:把一堆大于 1 的取到 1,把一堆大于 1 的取到 0,把两堆取到 0。三种选择恰好一种获胜,因此此时后手必胜。

当初始情况 $k = 2$ 时,先手想赢必须初始石子是一堆 $1$ 一个 $2$ 一个 $x$ 且 $n \mod 3 \neq 2$,先手把 $x$ 取干净或把 $x$ 取成 $1$。当初始情况 $k > 2$ 时,后手可以把 $n\ \text{mod}$ 调整对。先手无法避免 $k = 2$ 的情况,此时 $n \mod 3$ 不对,于是剩余情况后手必胜。

代码(Code)

#include<bits/stdc++.h>
#include<vector>
#define For(i,l,r) for(int i=l;i<=r;i++)
#define Rof(i,l,r) for(int i=l;i>=r;i--)
using namespace std;
#define P pair<int,int> 
#define int long long
#define x first
#define y second
inline int rd(){
	char c;bool f=false;while(!isdigit(c=getchar()))f=c=='-';int x=c^48;
	while(isdigit(c=getchar())){x=(((x<<2)+x)<<1)+(c^48);}return f?-x:x;
}const int inf = 0x3f3f3f3f3f3f3f3f;
const int N = 105;
bool ST;

int n,a[N];;

void Solve(){
	n=rd();For(i,1,n) a[i]=rd();
	sort(a+1,a+n+1);
	if(n%3==0 && a[n]==1) puts("Lose");else
	if(n==1 || a[n-1]==1) puts("Win");else
	if(n%3!=2 && a[n-2]==1 && a[n-1]==2) puts("Win");
	else puts("Lose");
}

bool ED;
signed main(){
	cerr<<abs(&ST-&ED)/1024./1024.<<"MB\n";
	freopen("stone.in","r",stdin);
	freopen("stone.out","a",stdout);
	int Tt=rd();double Tim=clock();
	while(Tt--) Solve();
	return cerr<<"TIME:"<<(clock()-Tim)/CLOCKS_PER_SEC,0;
}

文章作者: WolfDeer
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WolfDeer !
  目录