codeforces 1194D 1-2-K Game 题解

看到\(n,k \leq 10^9\) 差不多就是道结论题了

所以...开始推结论吧反正比赛时候弄了好久
能到达必败态的状态是必胜态,只能到达必胜态的状态是必败态

首先把题目转化 : 一堆石子有n个,每次可以取1个,2个或k个。
直到有一方无法操作,无法操作的一方输

假设状态为还剩下多少个石子
那么0就是必败态

1.考虑只有1,2没有k的情况
状态\(n\)可以到达\(n-1\)\(n-2\)
1,2能到达0 所以为必胜态
3只能到达1,2 所以为必败态
以此类推 \(3n\)是必败态,\(3n+1\)\(3n+2\)一定是必胜态 (n为非负整数)

其实原理也很简单...把石子三个三个一堆分 石子总数不是三的倍数的话 Alice先把余下1/2个取走 接下来Bob取i个Alice就取3-i个 必胜

否则Alice取i Bob就取3-i 最后Bob取完 Alice输

// W=Win,L=Lose
0 123 456 789...
L WWL WWL WWL...

结论:n为3的倍数则负 否则胜

2.k不为3的倍数
k的出现使得对于所有必败态i,i+k都会成为必胜态
但是 在只有1,2的情况下 对于任何必败态i 只有\(i+3j\)(j为非负整数)是必败态
k不是3的倍数 所以没有影响

// W=Win,L=Lose
0 123 456 789...
L WWL WWL WWL...

结论:同1

3.k为3的倍数
这时候 第一个变化的是k k原来是必败态 现在由于k可以直接转移到0 k成为了必胜态
这样使得原来的状态出现了一些改变
k+1会因此变成必败态(1,k-1,k是必胜态)

就像是这样:

012345............k.
LWWLWW...LWW...LWWWL
                   ^
                  k+1

由于每一个点i只能转移到\(i-1,i-2,i-k\) 这个多出来的W 本质上对k+1到2k的情况没有影响,这一段的情况是和情况1,2中k到2k-1的情况是一样的
(2k+1会受到k+1(L)的影响成为W 3k+2会受到2k+2(L)的影响成为W)

这就相当于在原序列的k,2k,3k...的位置 在前面插入了一个W

所以直接看作一个循环节为k+1的字符串...
而在每一个循环节中 对应的Lose是0,3,6...,k-3 也就是除了k以外所有3的倍数
其他都是Win

code:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
using namespace std;
typedef long long LL;

LL n,m,k,T;
LL a[500005] = {0};

int main(){
	cin >> T;
	while(T --){
		cin >> n >> k;
		if(k % 3 != 0) cout << ((n % 3 == 0) ? "Bob" : "Alice") << endl;
        // 情况2
		if(k % 3 == 0){
			k ++;
            // (n % k) 是取出n在k的循环节中为第几位(从0开始)
			if((n % k) % 3 == 0 && (n % k) != k - 1) cout << "Bob" << endl;
			else cout << "Alice" << endl;
		}
	}
	return 0;
}

The End

posted @ 2020-04-21 13:56  ItzInstallB  阅读(152)  评论(0编辑  收藏  举报