【2016杭电女生赛1007】【博弈 打表找规律】Alice and Bob 可走k步斜对角线的胜负态

#include<stdio.h> 
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }
const int N = 0, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;
int casenum, casei;
int Q, K, n, m;
int f[100][100];
int dp(int n, int m)
{
	if (n == 1 && m == 1)return 0;
	if (~f[n][m])return f[n][m];
	if (n > 1 && !dp(n - 1, m))return f[n][m] = 1;
	if (m > 1 && !dp(n, m - 1))return f[n][m] = 1;
	if (n > K&&m > K&&!dp(n - K, m - K))return f[n][m] = 1;
	return f[n][m] = 0;
}
void table(int k)
{
	K = k;
	for (n = 1; n <= 20; ++n)
	{
		for (m = 1; m <= 20; ++m)
		{
			MS(f, -1);
			printf("%d ", dp(n, m));
		}puts("");
	}
}
int main()
{
	//table(1);table(2);table(3);
	scanf("%d", &casenum);
	for (casei = 1; casei <= casenum; ++casei)
	{
		scanf("%d%d", &Q, &K); ++K; //首先先使得K+=1
		while (Q--)
		{	
			scanf("%d%d", &n, &m);

			//规律1:如果较小宽度为K的倍数,那么先手必胜
			if (n > m)swap(n, m); //n<=m
			if (n%K == 0)
			{
				puts("Alice");
				continue;
			}

			//规律2:距离顶角元素距离的奇偶性,一样对答案有所影响(特判K==2)
			int len = n / K;
			if (K > 2 && (len & 1))
			{
				puts((n + m) % 2 == 0 ? "Alice" : "Bob");
			}
			else
			{
				puts((n + m) % 2 == 0 ? "Bob" : "Alice");
			}
		}
	}
	return 0;
}
/*
【trick&&吐槽】
判定奇偶性的时候——
%2==1往往是错的,有时%2==-1。还是&1 来判定奇偶性的方法比较靠谱

【题意】
给你一个棋盘,大小为n*m。
我们一开始在(1,1)点,
如果我们当前在(x,y),
那么我们可以在一步之内走到
(x+1,y)
(x,y+1)
(x+k,y+k)
先告诉你k,k∈[1,1e9]
然后有q组询问,q∈[1,1000]
对于每个q,告诉你(n,m)
n∈[1,1e9],m∈[1,1e9]。
无法可走便输了,问先手必胜还是后手必胜。

【类型】
博弈 打表找规律

【分析】
对于这题,n和m都是1e9,太大了。
于是我们要考虑O(1)出解。
即打表找规律。
至于,什么是打表找规律呢?
1,问题数据规模很小,我们可以本地预处理出所有解,然后存到代表段数组中,O(1)输出
2,问题数据规模很大,我们可以本地跑出小数据的答案,然后猜解大数据的规律。

对于这题——
K==1时,表示这样的:
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

K==2时,表示这样的:
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
1 0 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 0 1 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0
0 1 1 0 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 0 1 1 0 1 1 0 1 0 1 0 1 0 1 0 1
0 1 1 0 1 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0
1 0 1 1 0 1 1 0 1 1 0 1 1 1 1 1 1 1 1 1
0 1 1 0 1 1 0 1 1 0 1 1 0 1 0 1 0 1 0 1
1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 0 1 0 1 0
0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 1 1 1 1 1
1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 0 1
0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 0 1 0
1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 1
0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1
1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0

K==3时,表示这样的:
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
1 0 1 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 0 1 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1
1 0 1 1 0 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0
0 1 0 1 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1
1 0 1 1 0 1 0 1 1 0 1 1 1 1 1 1 1 1 1 1
0 1 0 1 1 0 1 1 0 1 0 1 1 0 1 0 1 0 1 0
1 0 1 1 0 1 0 1 1 0 1 1 0 1 0 1 0 1 0 1
0 1 0 1 1 0 1 1 0 1 0 1 1 0 1 0 1 0 1 0
1 0 1 1 0 1 0 1 1 0 1 1 0 1 0 1 1 1 1 1
0 1 0 1 1 0 1 1 0 1 0 1 1 0 1 1 0 1 0 1
1 0 1 1 0 1 0 1 1 0 1 1 0 1 0 1 1 0 1 0
0 1 0 1 1 0 1 1 0 1 0 1 1 0 1 1 0 1 0 1
1 0 1 1 0 1 0 1 1 0 1 1 0 1 0 1 1 0 1 1

我们发现到,
对于K>1时,
对于f[K][K]~f[K][∞],答案都是1(先手必胜)
对于f[K][K]~f[∞][K],答案都是1(先手必胜)

对于f[2K][2K]~f[2K][∞],答案都是1(先手必胜)
对于f[2K][2K]~f[∞][2K],答案都是1(先手必胜)

对于f[3K][3K]~f[3K][∞],答案都是1(先手必胜)
对于f[3K][3K]~f[∞][3K],答案都是1(先手必胜)

......

即f[nK][nK]~f[nK][∞],答案都是1(先手必胜)
  f[nK][∞]~f[nK][nK],答案都是1(先手必胜)

对于其它的f(i,j),我们要找到第一个位置(pK,pK),满足i>=pK且j>=pK。

然后:
如果p是奇数,那么与(pK,pK)同奇偶性的(即横纵坐标之和同奇偶性)都是必胜点,否则为必败点
如果p是偶数,那么与(pK,pK)同奇偶性的(即横纵坐标之和同奇偶性)都是必败点,否则为必胜点

然而,对于K==1的时候,是特例的。不论p是奇数还是偶数,与(pK,pK)同奇偶性的(即横纵坐标之和同奇偶性)都是必败点,否则为必胜点


这里再尝试一下证明:(我们不妨把题目中的由从(1,1)->(n,m)),改变方向为从(n,m)走到(1,1),这样答案不变,然而考虑和看起来更直观。
对于初始K==1的,对于(n,m)==(X,X),初始点(先手)的胜负态为:
(1,1):必败态
(1,x)为(1,x-1)的反态,(x,1)为(x-1,1)的反态,为必胜态和必败态的依次轮转。
(2,2):必胜态
(2,x)和(x,2):都可以找到(1,x)和(1,x-1)的两个前驱,必然有必败态的前驱,所以全为必胜态
接下来所有点都找不到任何一个必败态的前驱,其状态又归回于——
(3,3):必败态
(3,x)为(3,x-1)的反态,(x,3)为(x-1,3)的反态,为必胜态和必败态的依次轮转。
(4,4):必胜态
(4,x)都可以找到(3,x)和(3,x-1)的两个前驱,(4,x)都可以找到(3,x)和(3,x-1)的两个前驱,必然有必败态的前驱,所以全为必胜态
……
所以我们对K==1条件下的结论是正确的

对于初始K>1的,我们不妨使得K+=1,然后,对于(n,m)==(X,X),初始点(先手)的胜负态为:
(1~K-1,x)与(x,1~K-1),这些点都是不涉及到斜着走K步的情况的,于是胜负只与奇偶性有关,即偶点必败奇点必胜。
(K,K):必胜态,因为其可以一步到(1,1)这个必败态。
(K,K~x)和(K~x,K),其既可以达到奇点,又可以达到偶点,所以是必胜态。

就是按照这个过程,奇偶归类,虽然很繁琐,然而我们可以得到结论的证明>_<

*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值