首先分析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 = 500005;
char f[300005];
int num[300005];
int number[300005];
int cnt = 0;
int aa, bb, cc;
int main() {
        int T;
        int a, b, aim;
        scanf("%d", &T);
        while (T--) {
                aim = cnt = 0;
                scanf("%d %d", &a, &b);
                scanf("%s", f + 1);
                int len = strlen(f + 1);
                for (int i = 1; i <= len + 1; i++) {
                        num[i] = 0;
                }
                for (int i = 1; i <= len; i++) {
                        num[i] = f[i] == '.' ? (num[i - 1] + 1) : 0;
                }
                for (int i = 1; i <= len + 1; i++)
                        if (num[i] == 0 && num[i - 1] > -0) {
                                number[++cnt] = num[i - 1];
                        }
                bool flag = 1;
                int now = 0;
                for (int i = 1; i <= cnt; i++) {
                        if (number[i] >= b && number[i] < a) {
                                flag = 0;
                                break;
                        }
                        if (number[i] >= 2 * b) {
                                if (aim == 0) {
                                        aim = i;
                                } else {
                                        flag = 0;
                                        break;
                                }
                        }
                        if (number[i] >= a && number[i] < 2 * b) {
                                now++;
                        }
                }
                if (flag == 0) {
                        printf("NO\n");
                } else {
                        if (aim == 0) {
                                if (now & 1) {
                                        printf("YES\n");
                                } else {
                                        printf("NO\n");
                                }
                        } else {
                                //cout<<" aim: "<<aim<<endl;
                                bool flag2 = 0;
                                int sum = number[aim];
                                for (int r1 = 0; sum - a - r1 >= 0; r1++) {
                                        int r2 = sum - a - r1;
                                        if (r1 >= 2 * b || (r1 >= b && r1 < a)) {
                                                continue;
                                        }
                                        if (r2 >= 2 * b || (r2 >= b && r2 < a)) {
                                                continue;
                                        }
                                        int add = 0;
                                        if (r1 >= a && r1 < 2 * b) {
                                                add++;
                                        }
                                        if (r2 >= a && r2 < 2 * b) {
                                                add++;
                                        }
                                        if ((now + add) % 2 == 0) {
                                                flag2 = 1;
                                                break;
                                        }
                                }
                                if (flag2) {
                                        printf("YES\n");
                                } else {
                                        printf("NO\n");
                                }
                        }
                }
        }
        return 0;
}
01-25 11:13