【博弈】CF-1194D.1-2-K Game

点击跳转到题目

目录

  • 题目描述
  • 思路
    • 1. k % 3 != 0
    • 2. k % 3 == 0
  • 代码

题目描述

给定一个 n 和 k,一个小兵初始位置在长度为 n 的线段上的第 n 个点,每次可以向左走 1 / 2 / k 格,Alice先移动这个小兵,Bob后移动这个小兵,最后不能移动的人为输家,问谁能获胜。

思路

在没有 k 的情况下考虑
当 n % 3 == 0 时,Bob 必能能走出一种走法使得每次移动到的位置都是3的倍数,Bob必胜状态
当 n % 3 == 1 或者 n % 3 == 2, Alice 必有一种走法使得每次让小兵移动的位置到 3 的倍数上面,把必败态转移给 Bob
加入 k 的状态时,需要考虑两种情况

1. k % 3 != 0

可以直接看成每次移动了 1 格或者 2 格,例如 k = 偶数 的时候,其为 2 的倍数,可以看成是走了多个 2 格的状态,当 k = 奇数 且 k % 3 != 0 时,可以看成走了多个 1 格状态。
所以给状态下 Bob 的必胜态:

if(k % 3 != 0)
	if(n % 3 == 0) 
		puts("Bob");

2. k % 3 == 0

可以知道当在 k 点时,可以直接移动到 0,为必胜态,接下来就需要考虑 k + 1 位置的一个状态。第 k + 1 位置的状态走 1 格到 k 状态会让对手胜,走 2 格走到 k - 1 状态,因为 (k - 1) % 3 != 0,根据最开始分析的三种情况,也是让对手胜,走 k 格到 1 状态,也是让对手胜,所以 k + 1 位置是一个必败点。Bob想要赢就必须要让 Alice 走到这个必败点。根据最先三种情况考虑,要让 Alice 走到 k + 1 点,因为中间有大量的重复路段,其实就是要 Alice 走到 m = n % (1 + k) 这个点,且这个 m 点不能等于 0,结合一下开始的 n % 3 == 0 的状态,Alice必走到这个点的状态就是 m % 3 == 0
最后注意一下这个 m != k,Alice直接获胜

if(k % 3 != 0) {
	int m = n % (k + 1);
	if(m % 3 == 0 && m != k) 
		puts("Bob");
}

代码

#include
using namespace std;

void solve() {
	int n, k;
	cin >> n >> k;
	if(k % 3 != 0) {
		if(n % 3 == 0) {
			puts("Bob");
			return;
		}
	}
	else {
		int m = n % (k + 1);
		if(m % 3 == 0 && m != k) {
			puts("Bob");
			return;
		}
	}
	puts("Alice");
}

int main() {
	int t; scanf("%d", &t); while(t--)
	solve();
	return 0;
}

你可能感兴趣的:(CodeForces)