【NC201610】Game

题目

Game

分解质因数,博弈

思路

博弈论一般是两极分化的,要么有思路,相当简单;要么没思路,死活想不出来。

所以一般先找规律,然后大胆猜想,最后提交验证

这道题有什么规律呢?

可以得出以下表格:

给定数先手赢
1
2
3
4
5
6
7
8
9
10

由以上表格,和再深入一点点的猜想,可以得出:

当给定数是 1 1 1 或者是素数时( 1 1 1 不是素数),先手输,因为素数的因子只有 1 1 1 和它本身,所以不可能分出非 1 1 1 的两个因子

那么对于合数呢?

既然上面牵扯到了素数(这是一个启发点),那么我们对合数的质因子进行研究,可以得出:

给定数先手赢
4 = 2 × 2 4=2\times 2 4=2×2
6 = 2 × 3 6=2\times 3 6=2×3
8 = 2 × 2 × 2 8=2\times 2\times 2 8=2×2×2
9 = 3 × 3 9=3\times 3 9=3×3
10 = 2 × 5 10=2\times 5 10=2×5

可以很明显地看出,当给定的数是质因子个数为 3 3 3 8 8 8 时,先手才输,其余情况的质因子个数都是 2 2 2,那么可否得出下面这个大胆的猜想呢?

当质因子个数为奇数时,先手输,否则,先手赢

这个猜想也能包含给定数是素数的情况(素数的质因子个数为 1 1 1)。但是不包含给定数是 1 1 1 的情况,所以 1 1 1 需要特判。

经过验证,这个猜想是正确的,但这里不给出证明

注意

题目求的是无法进行操作的人的名字

代码

#include <stdio.h>

/**
 * @brief 获取给定正整数的质因数个数
 *
 * @param n 一个给定的正整数
 * @return int 给定数的质因数个数
 */
int get_prime_fac_num(int n) {
    int res = 0, d = 2;
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            while (n % i == 0) {
                n /= i;
                res++;
            }
        }
    }
    if (n > 1) res++;
    return res;
}

/**
 * @brief 判断先手是否赢
 *
 * @param n 给定的数
 * @return int 0 表示输
 */
int check(int n) {
    // 如果给定数为 1 或者质因数个数为奇数,则先手输,否则先手赢
    return (n ^ 1) && !(get_prime_fac_num(n) & 1);
}

int main(void) {
    int n = 0;
    scanf("%d", &n);
    printf("%s\n", check(n) ? "Johnson" : "Nancy");
    return 0;
}
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木又可可

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值