题意:有n堆石头,每堆石头有a[i]个。H和N两个人轮流拿,每人最少拿1个。1代表H先拿,2代表N先拿。问H是否会赢。H每一回合会拿两次,但是N只能拿一次。
对于H先拿的情况,如果他可以拿(代表这个堆目前不为空),他一定会尽力改变自己现在的处境。那么什么时候他就改变不了了呢?就是拿完这一堆就没有了的时候。即这一堆的石头数目为1的时候。如果n堆石子,每堆只有一个石头,那么什么时候才是H先拿的必败态呢?就是n%30的时候。这样无论H怎么拿都不能赢。其余的时候就是H的必胜态。
对于N先拿的情况,极限情况也是石头个数为1的时候。N先拿,对于H来说,之要是N拿完之后,不是H的必败态,H就可以赢了。那就讨论N拿一次成为H必败态的情况。
①n1,无论怎么拿,H都输。
②设石头数目为1的堆有sum个,sumn并且n%31,这样无论怎么拿,H都输。
③设石头数目为1的堆有sum个,sumn-1&&n%31,N可以把不是1的那一堆拿完,而后就是H的必败态。
④设石头数目为1的堆有sum个,sumn-1&&n%30,N把不是1的那一堆拿成1,而后就是H的必败态。
代码如下:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxx=1e6+100;
ll a[maxx];
int n,k;
inline int read()
{
char ch = getchar(); int x = 0, f = 1;
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
} while('0' <= ch && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
} return x * f;
}
int main()
{
int t;
t=read();
while(t--)
{
n=read();k=read();
int sum=0;
int sum2=0;
for(int i=1;i<=n;i++)
{
a[i]=read();
if(a[i]==1) sum++;
if(a[i]==2) sum2++;
}
if(k==1)
{
if(n%3==0&&sum==n) puts("No");
else puts("Yes");
}
else
{
int flag=1;
if((sum==n-1&&n%3==0)||(n==1)||(sum==n&&n%3==1)||(sum==n-1&&n%3==1)) puts("No");
else puts("Yes");
}
}
}
博弈就是要冷静思考,思考两小时,写题五分钟。
努力加油a啊,(o)/~