Codeforces1537D Deleting Divisors (博弈)

题目链接: Deleting Divisors

大致题意

给定一个整数n. 操作: 把n减去一个因子, 这个因子不能是n和1.

现在Alice和Bob轮流对n进行操作, 谁不能操作谁就输了.

解题思路

考虑到最终的必败态: 这个数字为1 或者 这个数字是质数 则必败.

如果我们拿到的n是偶数(n != 2), 则我们一定可以进行操作. 我们可以把此时的n写作: n = 2k * odd1 * odd2 * … * oddq, 我们任意减去奇数因子, 对方一定拿到奇数. 一个奇数的因子一定是没有偶数的, 因此对方只能把n减去奇数因子, 相当于对方给我们了一个偶数. 如此反复, 我们可以必胜, 因为奇质数只会在对方的手中.


但这里有两个问题:
①我们只说了奇质数会在对方手中, 我们会不会拿到偶质数2呢?
②如果没有奇数因子呢? 相当于 n = 2k (k > 1)的形式. 或者随着游戏进行, n变成了2k的形式.

对于问题①, 我们拿不到2, 也拿不到2的整次幂(问题②), 因为没有一个奇数x的约数(不包括1和他自身), 与x差2的整次幂.

假设x为奇数, 不妨令 x = a * b. 此时如果a和b一奇一偶, 则a - b一定为奇数.

反之考虑a和b都是奇数的情况, 我们可以写成 x = a * (a + 2k) <==> x = (a * a) + (a * 2k), 此时 a * a一定为奇数, 而 a * 2k也是个奇数, 两个奇数相加, 结果一定是个偶数, 与x为奇数矛盾, 故不成立.

因此得证, 若n中有奇数因子, 先手确实必胜.


对于问题②, 相当于先手只能返还给对方一个偶数n’. 而此时, 如果n中含有奇数因子, 相当于交换了先后手, 此时先手必败. 因此我们一定返回给后手一个没有奇数因子的偶数, 因此我们只能给后手n' = n / 2. 此时后手也是这样的想法, 他会给我们 n'' = n' / 2.
如此反复, 我们发现, 如果n = 2k, k为奇数时, 先手必败, 反之必胜.

AC代码

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
int main()
{
	int t; cin >> t;
	while (t--) {
		int n; scanf("%d", &n);
		if (n == 1 or n == 2) { puts("Bob"); continue; }

		int k = log2(n);
		if (n == (1 << k)) printf("%s\n", k & 1 ? "Bob" : "Alice");
		else printf("%s\n", n & 1 ? "Bob" : "Alice");
	}
	return 0;
}

感觉分析细节是真的多QAQ, 当时比赛的时候也没想这么明白, 就猜了猜规律.

END

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

逍遥Fau

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

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

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

打赏作者

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

抵扣说明:

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

余额充值