问题链接(https://codeforces.com/problemset/problem/1194/D)
问题描述
先是划分出n+1个方格,编号从左到右是0到n。游戏从编号n开始,规定两人每次只能从右往左移动chip(碎片?)1、2或者k步。谁先不能移动(在0处不能移动),谁输,Alice先手。
进行T场游戏,每一场给出了n,k,输出每一场的胜利者的名字。
问题分析
下用x指代下标。
1、先看k不起作用的情况,即x<k。此时,玩家只能走1或者2。显然能发现一个特点,在1、2的玩家一定可以走到0,而在3的玩家只能走到1、2。由此可以推出在1、2的玩家必胜,而在3的玩家必败。再推广,4、5能走到3,6只能走到4、5,…。由于两个玩家每一步可操作步数是一样的,所以谁面对3m(3m为3的倍数)谁输,故在3m的玩家必败,而在3m+1或者3m+2的玩家总能走到3m使对手在必败,故3m+1,3m+2为必胜态,且这样的操作一轮下来必然走了3步。
2、再看k起作用的情况。当k为3m+1时,走k步,可以理解为走一步,在都重复无k时的几轮(3步)。那么情况和无k的情况是一样的,同样是面对3m的玩家必败。同理k=3m+2也是这样的。
当k为3m时,要从0开始说起。0为败态,那么x=0+k+1也为败态。为什么呢?从k+1的角度来讲,若走1步,对手到k,可以直接到0,故败;若走2步,则到k-1,由于k为3m,所以k-1=3m’+2,对手胜;若走k步,对手到1,可以直接到0,败。所以k+1必败。
同样的可以推广到若x为败态点,那么x+k+1也为败态点。由于x<k时的败态有0,3,…,3m(3m<k),所以在x>k时,有败态k+1,k+1+3,…,k+1+3m。这一步的推理与上面的近似,x+k+1若走1,对手可以走k到x;x+k+1若走k,对手可以走1到x;而x+k+1若走2,对手也走2,到x+k-3=(x-3)+k,由于x<k时的败态之间是相差3的,所以导致了x>k时,每一组败态也是相差3的,(体会每一组的意思,一组的败态个数为x<k的败态个数)。所以(x-3)+k也是败态,故面对x+k+1的玩家必败。
因为胜态总能让对手处于败态(所以才叫胜态和败态),所以每一轮必有一方处于败态,另一方为胜态。所以不妨设想当x>k时,加快游戏进度,败态只走k,那么胜态就只走1,那么每一轮总共走了k+1步,直到x<=k。我们就能很好地判断谁胜谁败了。
下是以k为6列的表,F表示谁面对这个位置谁输,W表示谁面对这个位置谁赢。
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
F | W | W | F | W | W | W | F | W | W | F | W | W | W | F |
代码如下
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int t,n,k;
cin>>t;
while(t--){
cin>>n>>k;
if(k%3==0) n%=k+1;
if(n==k||n%3) cout<<"Alice"<<endl;
else cout<<"Bob"<<endl;
}
return 0;
}