HDU 2177 取(2堆)石子游戏 威佐夫博弈

题目来源:HDU 2177 取(2堆)石子游戏

题意:中文

思路:判断是否是必败态就不说了 做过hdu1527就知道了

现在如果不是必败态 输出下一步所有的必败态 题目要求先输出两堆都取的方案

首先 a = b 直接2堆取完

a != b 因为bi = ai+i 现在知道ak 和 bk 那么 k = bk-ak 得到k 求出 aj 和 bj 如果ak-aj == bk-bj && ak-aj > 0(aj, bj)是必败态 输出aj bj

然后是只取一堆的情况

假设a不变 求出对应的bk 如果b > bk 输出a bk

假设b不变 求出对应的ak 如果a > ak 输出ak b

注意公式 ai = i*(sqrt(5.0)+1)/2 bi = ai+i

现在如果b不变 b = i*(sqrt(5.0)+1)/2+i = i*(sqrt(5.0)+3)/2 求出i然后求出 ak

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int main()
{
	int a, b;
	while(scanf("%d %d", &a, &b) && (a||b))
	{
		if(a > b)
			swap(a, b);
		//ai = i*(sqrt(5.0)+1)/2
		//bi = ai+i
		double k = (sqrt(5.0)+1)/2;
		double k2 = (sqrt(5.0)+3)/2;
		double i = (int)(a/k);
		double i2 = (int)(a/k2);
		int a1 = i*k, b1 = a1+i;
		int a2 = (i+1)*k, b2 = a2+i+1;
		int a3 = (i2*k), b3 = a3+i2;
		int a4 = (i2+1)*k, b4 = a4+i2+1;
		if(a1 == a && b1 == b)
			puts("0");
		else if(a2 == a && b2 == b)
			puts("0");
		else
		{
			puts("1");
			if(a == b)
				printf("%d %d\n", 0, 0);
			else
			{
				int j = b-a;
				int a3 = j*k, b3 = a3+j;
				if(a-a3 == b-b3 && a-a3 > 0)
					printf("%d %d\n", a3, b3);
			}
			if(a1 == a && b1 < b)
				printf("%d %d\n", a1, b1);
			if(a2 == a && b2 < b)
				printf("%d %d\n", a2, b2);
			if(a3 < b && b3 == a)
				printf("%d %d\n", a3, b3);
			if(a4 < b && b4 == a)
				printf("%d %d\n", a4, b4);

		}

	}
	return 0;
}

HDU 2177 取(2堆)石子游戏 威佐夫博弈

时间: 2024-12-15 01:45:50

HDU 2177 取(2堆)石子游戏 威佐夫博弈的相关文章

hdu 2177 取(2堆)石子游戏 (威佐夫博奕)

//,在威佐夫博奕的基础上新增加了一条要求:就是如果在赢得条件下,输出第一步怎么走. # include <stdio.h> # include <algorithm> # include <iostream> # include <math.h> # include <string.h> using namespace std; int main() { int a,b,i,k; while(~scanf("%d%d",&a

hdu 2177 取(2堆)石子游戏

天资愚笨啊,网上的一大堆没看懂...... 总结百科的方法为: 1.a==b 同时减去a 得到0,0 2.a==a_k      b>b_k b -(b-b_k) 3.a==a_k     b<b_k 同时拿走a_k-a_(b-a_k) 得到 a_(b-a_k)    a_(b-a_k) + b-a_k 4.a>a_k       b==b_k 从a中拿走 a-a_k 5.a<a_k       b==b_k 5.1 a==a_ j   (j<k) b-(b-b_ j) 得到

hdu 2177 取(2堆)石子游戏 博弈论,,威佐夫博奕 ,提高题,不过测试数据奇水无比

取(2堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1291    Accepted Submission(s): 764 Problem Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相

HDU 2117 取(2堆)石子游戏【wzf博弈】

题意:威佐夫博弈原型,除了输出先手能不能胜,还要输出先手的第一手选择. 思路:预处理出1000000以内的所有奇异局势.对于每个自然数,其必然是某一个奇异局势的a或者b.故对于一个非奇异局势,必定有一个且一个只取一堆石子的操作使得当前局势变成奇异局势. #include<stdio.h> #include<string.h> #include<math.h> #include<iostream> using namespace std; int a[4000

hdu 2177 取(2堆)石子游戏(威佐夫博奕)

题目链接:hdu 2177 这题不是普通的 Nim 博弈,我想它应该是另一种博弈吧,于是便推 sg 函数打了个 20*20 的表来看,为了方便看一些,我用颜色作了标记,打表代码如下: 1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #include<map> 5 #include<algorithm> 6 #include<windows.h> 7 using n

HDU 2176 取(m堆)石子游戏 尼姆博弈

题目思路: 对于尼姆博弈我们知道:op=a[1]^a[2]--a[n],若op==0先手必败 一个简单的数学公式:若op=a^b 那么:op^b=a: 对于第i堆a[i],op^a[i]的值代表其余各个堆值的亦或值. 我们现在希望将a[i]改变成某个更小的值使得,op^a[i]=0,反过来a[i]=op^0,输出它就好了 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h&

HDU 1527 取石子游戏 威佐夫博弈

题目来源:HDU 1527 取石子游戏 题意:中文 思路:威佐夫博弈 必败态为 (a,b ) ai + i = bi     ai = i*(1+sqrt(5.0)+1)/2   这题就求出i然后带人i和i+1判断是否成立 以下转自网上某总结 有公式ak =[k(1+√5)/2],bk= ak + k  (k=0,1,2,-,n 方括号表示取整函数) 其中出现了黄金分割数(1+√5)/2 = 1.618-,因此,由ak,bk组成的矩形近似为黄金矩形 由于2/(1+√5)=(√5-1)/2,可以先

HDU 2176 取(m堆)石子游戏 博弈

取(m堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3598    Accepted Submission(s): 2151 Problem Description m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子.例如5堆 5,7,8,9,10先取者胜,先取者第1次取

HDU 2176 取(m堆)石子游戏 (Nim博弈)

取(m堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1937    Accepted Submission(s): 1115 Problem Description m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子.例如5堆 5,7,8,9,10先取者胜,先取者第1次取