P4236 【扑克】题解
本题属于一打表就太容易发现规律的题目。
首先上结论:
当a是奇数时,n为奇数则先手胜,反之则后手胜。
当a是偶数时,求n 对 a+1取模的值,这个值如果是奇数或等于a,则先手胜,否则后手胜。
可以很容易想到要把n转化为一个a进制的数。此时,两个操作转化成这样:
①选择非0的一位,使之-1
②选择0的一位,使之变为a-1,而对于这一位前面的所有位,如果也是0那么也变为a-1,直到遇到一个非0位使之-1.
所以,当a是奇数时,可以注意到无论原数是如何,选择了什么操作,每一次行动都会让原数二进制表达上每一位的和的奇偶性变化。而这一切的终点则是“1”的那个时候->先胜点,和为奇数。因此,初始局面的每一位的和如果是奇数那么先胜,否则后手胜。
而又不难发现,a为奇数时,a进制表达上的每一位
而a是偶数的时候则稍微复杂一些。
首先,想到a+1,你是需要发现它除了n < a且n为偶数的情况n = a+1应该算是一个显然的必败点了。在它以后的情况都是比较好分析的。
当局面变化到n < a+1的时候,由于只有-1或者-a的操作,可以显然得到如果n为偶数且
由于
所以,对于任意的一个偶数
于是,如果是后手胜局,它可以容易在先手行动以后选择拿走
代码很简单:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 20010;
bool a[maxn];
int n,m,p,q,mi[20],ans[20];
char ch[510];
inline int read()
{
int x = 0, f = 1;
char ch = 0;
for (;!isdigit(ch);ch = getchar()) if (ch == '-') f = -1;
for (;isdigit(ch);ch = getchar()) x = x *10 + ch - 48;
return x * f;
}
int main()
{
q = read();
while (q--)
{
n = read(); scanf("%s",ch);
int len = strlen(ch);
if (n&1)
{
if (ch[len - 1]&1) puts("lsq Win"); else puts("wzt Win");
}
else
{
n++;
int now = 0;
for (int i = 0; i < len; ++i)
{
now = now * 10 + ch[i] - 48;
now %= n;
}
if ((now) & 1 || now == n - 1) puts("lsq Win"); else puts("wzt Win");
}
}
}
话说比赛的时候,这个题我首先是早上起来看了一下然后就被拉去走亲戚了,但是整个过程中都没想到啥觉得很肯定的结论,然后回到家试着一打表看看就发现....