首先分析A能获胜的情况 A能获胜 当且仅当A拿完后所有剩下的都<b

所以一旦存在一个大小为X的 且 b<=X<a 则必是后手赢

当X为 a<=x<2*b 的时候 无论A或B拿 两个人都只能拿一次 拿完就<b作废

而X>=2*b时 如果是B先手 则B可以构造出一个大小刚好为b的来赢得胜利 所以如果有两个及以上的X>=2*b 后手必胜

当有且仅有一个X>=2*b时 A肯定要先操作这块来获得胜利 A能获胜 当且仅当 A拿完后的块只能在[1,b)和[a,2*b)这个范围内

因为一旦出现[b,a)或者[2*b,无穷)这两个范围内的块 A必输 所以我们只要暴力枚举 看是否存在A取完后 [a,2*b) 范围内的块为偶数的情况即可

#include<bits/stdc++.h>
#define RG register
using namespace std;
typedef long long ll;
const int MAXN = ;
char f[];
int num[];
int number[];
int cnt = ;
int aa, bb, cc;
int main() {
int T;
int a, b, aim;
scanf("%d", &T);
while (T--) {
aim = cnt = ;
scanf("%d %d", &a, &b);
scanf("%s", f + );
int len = strlen(f + );
for (int i = ; i <= len + ; i++) {
num[i] = ;
}
for (int i = ; i <= len; i++) {
num[i] = f[i] == '.' ? (num[i - ] + ) : ;
}
for (int i = ; i <= len + ; i++)
if (num[i] == && num[i - ] > -) {
number[++cnt] = num[i - ];
}
bool flag = ;
int now = ;
for (int i = ; i <= cnt; i++) {
if (number[i] >= b && number[i] < a) {
flag = ;
break;
}
if (number[i] >= * b) {
if (aim == ) {
aim = i;
} else {
flag = ;
break;
}
}
if (number[i] >= a && number[i] < * b) {
now++;
}
}
if (flag == ) {
printf("NO\n");
} else {
if (aim == ) {
if (now & ) {
printf("YES\n");
} else {
printf("NO\n");
}
} else {
//cout<<" aim: "<<aim<<endl;
bool flag2 = ;
int sum = number[aim];
for (int r1 = ; sum - a - r1 >= ; r1++) {
int r2 = sum - a - r1;
if (r1 >= * b || (r1 >= b && r1 < a)) {
continue;
}
if (r2 >= * b || (r2 >= b && r2 < a)) {
continue;
}
int add = ;
if (r1 >= a && r1 < * b) {
add++;
}
if (r2 >= a && r2 < * b) {
add++;
}
if ((now + add) % == ) {
flag2 = ;
break;
}
}
if (flag2) {
printf("YES\n");
} else {
printf("NO\n");
}
}
}
}
return ;
}
05-19 11:05