题目大意:有n个石子放在一堆,每次操作可以选择拿走k个石子,然后将那一堆剩下的分成两堆,新堆不能为空,如果某一堆石子数小于等于k,可以直接拿完那一堆,不能操作的人输掉,A先B后问谁能赢
2<=k<=1e7;0<=n<=1e9
思路:我们先讨论k确定的情况,n=0时,先手不能操作,sg[0]=0,n=1~k时,都只能转移到0,sg[1]=1,n=k+1时,不能转移到其他位置,sg[k+1]=0,在n>k+1时,就需要讨论分堆的情况,从1到n枚举分出的其中一堆的石子数量i,另一堆的数量j即为x-k-i(x为当前枚举的石子数量),如果j>0,那么这时就分成了两个子游戏,所以sg[x]=sg[i]^sg[j],我们照此计算出k=2,3,4时先手必败也就是sg[i]=0的情况,发现除了sg[k+1]=0以外,之后n每增加4k+2,sg[n]都等于0,所以我们得出结论当(n-(k+1))%(4k+2)=0时先手必输,否则先手必胜
//#include<__msvc_all_public_headers.hpp>
#include<bits/stdc++.h>
using namespace std;
//int k;
//typedef long long ll;
//ll sg[1005];
//ll f(ll x)
//{//递归计算sg值
// if (sg[x] != -1)
// {//记忆化搜索
// return sg[x];
// }
// set<ll>s;
// for (int i = 1; i <= x; i++)
// {//分堆
// int j = x - i - k;
// if (j <= 0)
// continue;
// s.insert(sg[i] ^ sg[j]);
// }
// int now = 0;
// while (s.count(now))
// {//找MEX
// now++;
// }
// return now;
//}
//int main()
//{
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
// cin >> k;
// memset(sg, -1, sizeof sg);
// sg[0] = 0;
// for (int i = 1; i <= k; i++)
// {
// sg[i] = 1;
// }
// for (int i = k + 1; i <= 1000; i++)
// {
// sg[i] = f(i);
// }
// for (int i = 1; i <= 1000; i++)
// {
// if (!sg[i])
// {
// cout << i << " " << sg[i] << endl;
// }
// }
// return 0;
//}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
{
int k, n;
cin >> k >> n;
if ((n - k - 1) % (4 * k + 2) == 0)
{
cout << "Bob" << endl;
}
else
cout << "Alice" << endl;
}
}