Poj-3922 A simple stone game(k倍动态减法)
题意:
游戏是这样的:两个玩家以一堆n个石头开始游戏。他们轮流从石堆里取石头,每次至少取一块。先走的人第一步最多可以拿n-1块石头。从那时起,一个玩家最多可以拿k倍于他的对手上次拿的石头。例如,如果一个玩家轮流拿m块石头,那么另一个玩家下一次最多可以拿k×m块石头。谁拿了最后一块石头,谁就赢了这场比赛。
题解:
原文:k倍动态减法
斐波那契博弈是本题当k==2的一种特殊情况:
当k==1的时候:
当n=2^i (i^2 把i和2按位异或) 的多少次方的时候,那么这就是一个必败态,因为此时k==1,那么你把它化为二进制,这个时候拿掉二进制的最后一个1,那么对方必然不能拿走倒数第二位的1,因为他不能拿的比你多。你只要按照这个策略对方一直都不可能拿完。所以你就会赢。
而当分解的二进制中只有一个1时,因为第一次先手不能全部取完,所以后手一定有办法取到最后一个1,所以必败!
举个例子,当 n = 6 = (110)时:
第一轮:先手第一次取最右边的1,即2个,此时还剩4(100)个,后手能取1或2个;
第二轮:假如上轮后手取的两个,先手再取两个直接赢了
假如后手取了一个,那么还剩三个,自己只能去1个,以后也只能取一个,所以必胜!
当 k = 2 时,赤裸裸的Fibonacci博弈了,具体这儿不多说,自己再上述博客已写的很明白了。其实n经拆解后也可以表示成二进制的形式,用 k = 1时的方法来理解,比如 n = 11 = 7 + 3 + 1,可表示成 10101;
当 k 取任意非零正值时,重点来了:
犹如Fibonacci博弈,我们首先要求一个数列,将n分解成数列中一些项的和,然后就可以按Fibonacci博弈的解决方法来完成,也可以按二进制的方法来理解,每次取掉最后一个1 还是符合上面的条件。
我们用a数组表示要被求的数列,b数组中的b[i]保存 a[0...i] 组合能够构造的最大数字。这儿有点难理解,所谓构造就是指n分解为Fib数相加的逆过程。举例说明,当k = 2 时,a[N]={1, 2, 3, 5, 8, 13, 21, 33....} (Fibonacci数组);那么b[3] 即 1、2、 3 能够构造的最大数字,答案是4,有点匪夷所思?或许你会问为什么不是5、6或者其它的什么,其实是这样的
,4 能分解成 1+3 是没有争议的,但5能分解成2+3吗? 不能,因为5本身也是Fibonacci数;6虽然能分解,但不是分解成1+2+3,而是分解成1+5。
经过上述,我们知道b[i] 是 a[0...i] 能够构造出的最大数字,那么a[i +1] = b[i]+1;因为a数组(Fib数组)所存的数字都是不可构造的(取到它本身就是必败态),显然a[0...i]构造的最大数字 + 1 即为下一个不可构造的数字了(a[i + 1])。
然后关于b[i]的计算,既然是a[0...i]构造最大数字,那么 a[i]是一定要选用的(这儿需要一定的推理,a[i]构造数字时,相邻的j个是不能同时用的,就像上述的2、3不能构造出5一样,推理请自己完成),那么要选用的下一项只能递减寻找,直到找到
a[t] 满足 a[t] * K < a[i] ,而b[t]就是a[0...t]所能构造的最大数字,再加上a[i], 即为a[0...i]能构造的最大数字,于是b[i] = b[t] + a[i]。
求的数列后,之后的工作就简单了,跟Fibonacci博弈一样一样的,如果n=数列中的数,则必败,否则必胜;必胜时还要求输出第一步取法,其实就是分解的数列中最小的一个
代码:
1 #include<stdio.h>
2 #include<string.h>
3 #include<iostream>
4 #include<algorithm>
5 using namespace std;
6 const int maxn=20000005;
7 int a[maxn],b[maxn];
8 int main()
9 {
10 int t,k,n,p=0;
11 scanf("%d",&t);
12 while(t--)
13 {
14 scanf("%d%d",&n,&k);
15 a[0]=b[0]=1;
16 int i=0,j=0;
17 while(n>a[i])
18 {
19 i++;
20 a[i]=b[i-1]+1;
21 while(a[j+1]*k<a[i])
22 j++;
23 if(k*a[j]<a[i])
24 b[i]=b[j]+a[i];
25 else b[i]=a[i];
26 }
27 if(n==a[i])
28 printf("Case %d: lose\n",++p);
29 else
30 {
31 int ans=0;
32 while(n)
33 {
34 if(n>=a[i])
35 {
36 n-=a[i];
37 ans=a[i];
38 }
39 i--;
40 }
41 printf("Case %d: %d\n",++p,ans);
42 }
43 }
44 return 0;
45 }
Poj-3922 A simple stone game(k倍动态减法)的更多相关文章
- uva 1567 - A simple stone game(K倍动态减法游戏)
option=com_onlinejudge&Itemid=8&page=show_problem&problem=4342">题目链接:uva 1567 - ...
- hdu 2486/2580 / poj 3922 A simple stone game 博弈论
思路: 这就是K倍动态减法游戏,可以参考曹钦翔从“k倍动态减法游戏”出发探究一类组合游戏问题的论文. 首先k=1的时候,必败态是2^i,因为我们把数二进制分解后,拿掉最后一个1,那么会导致对方永远也取 ...
- ZOJ 3599 K倍动态减法游戏
下面的文字辅助理解来自http://blog.csdn.net/tbl_123/article/details/24884861 博弈论中的 K倍动态减法游戏,难度较大,参看了好多资料才懵懂! 此题可 ...
- POJ 3922 A simple stone game
题目: E - A simple stone game Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d &am ...
- Something about 博弈(POJ 3922 A simple stone game)
先是题目,本来是第三次训练的题,在这特别提出来讲. 先是题目: E - A simple stone game Time Limit:1000MS Memory Limit:65536KB ...
- K倍动态减法游戏
题目:http://acm.hdu.edu.cn/showproblem.php?pid=2580 #include <iostream> #include <string.h> ...
- HDU2486_A simple stone game
这个题目是这样的,一堆石子有n个,首先第一个人开始可以去1-(n-1)个,接下来两人轮流取石子,每个人可取的石子数必须是一个不超过上一次被取的石子的K倍的整数. 现在求对于一堆数量为n的石子是否为必胜 ...
- POJ 3922A Simple Stone Game
题目链接 A Sample Stone Game 题目大意:给定n,k,表示最初时有n个石头,两个人玩取石子游戏,第一个人第一次可以取1~n-1个石头,后面每个人最多可以拿走前面一个人拿走的个数的K倍 ...
- HDUOJ--------A simple stone game(尼姆博弈扩展)(2008北京现场赛A题)
A simple stone game ...
随机推荐
- LeetCode24 两两交换链表中的节点
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表. 示例: 给定 1->2->3->4, 你应该返回 2->1->4->3. 说明: 你的算法只能使用常数的 ...
- python模块详解 | progressbar
参考官方文档:https://pypi.org/project/progressbar/#description progressbar 安装: pip install progressbar pro ...
- VmwareTools显示灰色无法安装
VMware不安装VMware Tools无法全屏,然后实机之间不能传输文件等. 安装Vmware Tools显示是灰色的,详细解决方案如下 打开虚拟机设置,CD/DVD 选择ISO映像文件 在Vmw ...
- Can't locate Time/HiRes.pm in @INC (@INC contains
Can't locate Time/HiRes.pm in @INC (@INC contains: /usr/local/lib/perl5 /usr/local/share/perl5 /usr/ ...
- python无法连接mysql,有个小坑,需要注意一下!
尝试用python链接mysql数据库,按照教程里链接了小半夜,就是没有链接上,找了各种文章,最后发现是版本的问题,我想使用的模块是MySQLdb,刚刚去他们的官网看了一下,最近一次更新是2014年, ...
- HTML5表格详细教程
HTML5表格 文章目录 HTML5表格 5.1 定义表格 5.1.1 普通表格.列标题 5.1.2 表格标题 5.1.3 表格行分组.表格列分组 5.2 表格属性 5.2.1 单线表格.分离单元格 ...
- [CPP] STL 简介
STL 即标准模板库(Standard Template Library),是 C++ 标准库的一部分,里面包含了一些模板化的通用的数据结构和算法.STL 基于模版的实现,因此能够支持自定义的数据结构 ...
- Spring Boot(IDEA,Gradle)超详细用户管理项目(一)——Hello World
1.构建工具的配置(Gradle):自定义-所有设置:构建.执行.部署-构建工具-Gradle: 设置Gradle用户主目录:(该目录相当于仓库,gradle将下载所需依赖到此目录下),此目录下可新建 ...
- python 编译EXE文件
以labelme测试 标注工具labelimg和labelme 矩形标注工具:labelimg 多边形标准工具:labelme 前者官网发布了可执行文件,后者只有python源码,如果需要编译wind ...
- JavaScript学习总结(基础知识)
js代码引入 方式1: <script> alert('欢迎来到德玛西亚!') </script> 方式2:外部文件引入 src属性值为js文件路径 <script sr ...