题目链接
题目描述
有一堆石子,共 个。Alice 和 Bob 两位玩家轮流行动,Alice 先手。每人每次可以从堆中取走
个石子,其中
。如果轮到某位玩家时,剩余石子数小于
,则该玩家无法操作,判负。取走最后一个石子的一方获胜。假设双方都采取最优策略,判断先手能否必胜。
解题思路
本题是巴什博弈的扩展形式。标准的巴什博弈允许取 个石子,而本题允许取
个。解题的核心思想仍然是寻找游戏状态的周期性,并划分出周期内的“必胜态”与“必败态”。
-
寻找状态周期 通过博弈论的归纳分析可以证明,此类取石子游戏的胜负状态是以
为周期循环的。也就是说,一个有
个石子的局面,其胜负性质等同于一个有
个石子的局面。
-
划分周期内的必败态 在一个周期内,即石子数
满足
时,我们需要确定哪些是必败态。
- 根据规则,如果轮到某个玩家时,石子数小于
,该玩家就无法行动,直接判负。
- 因此,石子数在区间
内的局面都是必败态。
- 根据规则,如果轮到某个玩家时,石子数小于
-
划分周期内的必胜态
- 如果一个局面
允许玩家通过一次操作(取
个石子)将局面转移到一个必败态
,那么局面
就是一个必胜态。
- 对于区间
内的任何局面
,玩家总可以找到一个合法的取石子数量
(其中
),使得剩余的石子数
落在必败区间
中。因此,这些局面都是必胜态。
- 如果一个局面
-
最终结论 结合以上两点,我们可以得到一个简单的判断法则:
- 首先计算
在一个周期内的等效状态:
。
- 然后判断这个等效状态
是否落在必败区间内。
- 如果
,则初始局面
是一个必败态,先手必败(Bob 胜)。
- 如果
,则初始局面
是一个必胜态,先手必胜(Alice 胜)。
- 首先计算
代码
#include <iostream>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;
while (t--) {
long long n, m1, m2;
cin >> n >> m1 >> m2;
long long r = n % (m1 + m2);
if (r >= m1) {
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
}
return 0;
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(System.out);
String tStr = br.readLine();
if (tStr == null) return;
int t = Integer.parseInt(tStr);
while (t-- > 0) {
StringTokenizer st = new StringTokenizer(br.readLine());
long n = Long.parseLong(st.nextToken());
long m1 = Long.parseLong(st.nextToken());
long m2 = Long.parseLong(st.nextToken());
long r = n % (m1 + m2);
if (r >= m1) {
out.println("YES");
} else {
out.println("NO");
}
}
out.flush();
out.close();
}
}
import sys
def solve():
t_str = sys.stdin.readline()
if not t_str:
return
t = int(t_str)
for _ in range(t):
line = sys.stdin.readline()
if not line:
break
n, m1, m2 = map(int, line.split())
r = n % (m1 + m2)
if r >= m1:
print("YES")
else:
print("NO")
solve()
算法及复杂度
- 算法: 博弈论 (扩展巴什博弈)
- 时间复杂度: 对于每组测试数据,我们只进行了一次取模和几次判断操作,时间复杂度为
。总的时间复杂度为
,其中
是测试数据的组数。
- 空间复杂度: 没有使用额外的存储空间,空间复杂度为
。