G Stones

原博客地址
https://blog.csdn.net/weixin_39792252/article/details/81448795

博弈问题
终止条件

  1. 某一个人不能再拿
  2. 某一个人取完了一堆石子

首先考虑的就是如果有石子的堆数量在a,b之间,那么直接取完这一堆直接结束游戏了,在计算grundy值 的时候也不会出现a,b的grundy值(不会留给对手必胜的机会)
打表grundy值,发现规律,循环节是a+b,grundy(i) = i%(a+b)/a;

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5+7;
ll x[maxn], a, b, n;
 
int SG[maxn],S[maxn];
 

 
ll check(ll m) {
    m %= (a+b);
    m /= a;
    if(m == 0) return 1;
    else if(m == 1) return 0;
    else return m;
}
 
int main()
{
     //printf("a , b : %d %d\n", 2, 5);
     //getSG(100, 1, 6);
     //cout<<endl;
     int t; scanf("%d", &t);
     while(t--)
     {
         scanf("%lld%lld%lld", &n, &a, &b);
         for(int i = 0; i < n; i++) scanf("%lld", &x[i]);
 
         bool f = false;
         ll res = 0;
 
         for(int i = 0; i < n; i++) if(x[i]>=a&&x[i]<=b) { f = true; break; }
         if(f) { puts("Yes"); continue; }
 
         if(a == 1) for(int i = 0; i < n; i++) res ^= ((x[i] - b - 1)%(a+b));
         else for(int i = 0; i < n; i++)
              if(x[i] > b) res ^= check(x[i] - b);
         if(res == 0) puts("No");
         else puts("Yes");
     }
}