题目链接
题目描述
小红(kou)和小紫(yukari)在玩一个游戏。她们有一个正整数 x
,两人轮流操作。小红先手。
每次操作,当前玩家需要选择 x
的一个质因子 p
,然后将 x
替换为 x / p
。
当一个玩家无法操作时(此时 x
变为 1),该玩家输掉游戏。
假设两人都足够聪明,采取最优策略,请问谁会获胜?
解题思路
这是一个典型的公平博弈游戏(Impartial Game),因为在任何状态下,可以执行的操作只取决于当前的状态(数字 x
),而与轮到哪位玩家无关。
这类问题的关键在于分析游戏的总步数。
-
游戏的核心:每次操作都是将
x
除以其一个质因子。这等价于从x
的所有质因子(包含重复的)集合中拿走一个。 -
游戏结束的条件:当
x
变为 1 时,游戏结束,因为 1 没有任何质因子。 -
总步数是固定的:无论每次选择哪个质因子,游戏都会在固定的步数后结束。这个总步数等于
x
的质因子总数(计入重复的)。例如,对于x = 12 = 2 * 2 * 3
,质因子有2, 2, 3
共三个。无论先除以2还是3,游戏都将进行恰好 3 步。12 -> 6 -> 3 -> 1
(3步)12 -> 4 -> 2 -> 1
(3步)
-
胜负判断:既然总步数是固定的,设为
k
,问题就变得非常简单了:- 小红先手。她走第 1, 3, 5, ... 步。
- 小紫后手。她走第 2, 4, 6, ... 步。
- 如果总步数
k
是奇数,那么最后一步(第k
步)必然是由小红走的。小红走完后,x
变为 1,轮到小紫时无法操作,所以小红获胜。 - 如果总步数
k
是偶数,那么最后一步(第k
步)必然是由小紫走的。小紫走完后,x
变为 1,轮到小红时无法操作,所以小紫获胜。
-
算法实现:问题就转化为了求解一个数
x
的质因子总数k
,然后判断k
的奇偶性。- 我们可以用和上一题“分解质因数”类似的试除法来计算
k
。 - 遍历
i
从 2 到sqrt(x)
,每次发现x
能被i
整除,就计数加一,并更新x
。 - 最后,如果
x
还不为 1,说明它本身也是一个质因子,计数再加一。
- 我们可以用和上一题“分解质因数”类似的试除法来计算
代码
#include <iostream>
using namespace std;
void solve() {
long long x;
cin >> x;
long long count = 0;
for (long long i = 2; i * i <= x; ++i) {
while (x % i == 0) {
count++;
x /= i;
}
}
if (x > 1) {
count++;
}
if (count % 2 != 0) {
cout << "kou" << endl;
} else {
cout << "yukari" << endl;
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while (t-- > 0) {
solve(sc);
}
}
public static void solve(Scanner sc) {
long x = sc.nextLong();
long count = 0;
for (long i = 2; i * i <= x; i++) {
while (x % i == 0) {
count++;
x /= i;
}
}
if (x > 1) {
count++;
}
if (count % 2 != 0) {
System.out.println("kou");
} else {
System.out.println("yukari");
}
}
}
t = int(input())
for _ in range(t):
x = int(input())
count = 0
i = 2
while i * i <= x:
while x % i == 0:
count += 1
x //= i
i += 1
if x > 1:
count += 1
if count % 2 != 0:
print("kou")
else:
print("yukari")
算法及复杂度
- 算法:博弈论、质因数分解
- 时间复杂度:
。其中
T
是测试用例的数量。对于每个x
,我们需要运行一次试除法,其复杂度为。
- 空间复杂度:
。我们只需要常数级别的额外空间来存储变量。