先是题目,本来是第三次训练的题,在这特别提出来讲。

先是题目:

E - A simple stone game Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit   Status   Practice   POJ 3922 Description After he has learned how to play Nim game, Mike begins to try another stone game which seems much easier.

The game goes like this: Two players start the game with a pile of n stones. They take stones from the pile in turn and every time they take at least one stone. The one who goes first can take at most n-1 stones for his first move. From then on a player can take at most k times as many stones as his opponent has taken last time. For example, if one player take m stones in his turn, then the other player can take at most k * m stones next time. The player who takes the last stone wins the game. Suppose that those two players always take the best moves and never make mistakes, your job is to find out who will definitely win the game. Input The first line contains a integer t, indicating that there are t test cases following.(t<=20). Each test case is a line consisting of two integer n and k.(2<=n<=10 8,1<=k<=10 5). Output For each test case, output one line starting with “Case N: ”, N is the case number. And then, if the first player can ensure a winning, print the minimum number of stones he should take in his first turn. Otherwise, print "lose". Please note that there is a blank following the colon. Sample Input 5 16 1 11 1 32 2 34 2 19 3

Sample Output  Case 1: lose Case 2: 1 Case 3: 3 Case 4: lose Case 5: 4

Hint When k = 1, the first player will definitely lose if the initial amount of stones is in the set {2, 4, 8, 16, 32, ...}. Let's call this kind of set “first-player-lose set”.

When k = 2, the first-player-lose set is {2, 3, 5, 8, 13, 21, 34, 57 ...} , which happens to be the Fibonacci sequence starting from 2.

先是一大神解法&分析:

来自:http://hi.baidu.com/lccycc_acm/item/a6f0dd0ec5c44a39f3eafcd3

两人取一堆n个石子 先手不能全部取完 之后每人取的个数不能超过另一个人上轮取的数*K

给n,K判断先手必胜并求第一步

博弈题

这题的思考过程非常有意义。

当k=1的时候 可知必败局面都是2^i  将n分解成二进制,然后先手取掉最后一个1.然后对方必然无法去掉更高的1,而对方取完我方至少还能拿掉最后一个1 导致对方永远取不完。

当k=2的时候,必败局面都是斐波那契数列。利用“先手去掉最后一个1,则后手必不能去掉更高阶的1导致取不完”的思想,斐波那契数列有一个非常好的性质就是:任意一个整数可以写成斐波那契数列中的不相邻的项的和,于是将n写成这种形式,先取走最后一个1,对方能取的数是这个数*2,小于高2位的1,所以取不完。

当K的时候, 想办法构造数列,将n写成数列中一些项的和,使得这些被取到的项的相邻两个倍数差距>k 那么每次去掉最后一个1 还是符合上面的条件。设这个数列已经被构造了i 项,第 i 项为a[ i ],前 i 项可以完美对1..b[ i ] 编码使得每个编码的任意两项倍数>K 那么有

a[ i+1 ] = b[ i ] + 1;这是显然的 因为b[ i ] + 1没法构造出来,只能新建一项表示

然后计算b[ i+1] 既然要使用 a[ i+1 ] 那么下一项最多只能是某个 a[ t ] 使得 a[ t ] * K < a[ i+1 ] 于是

b[ i ] = b[ t ] + a[ i+1 ]

然后判断n是否在这个数列里面

如果在,那么先手必败。否则不停的减掉数列a中的项构造出n的分解,最后一位就是了。

代码:

 #include<stdio.h>
#define N 2000000
int a[N],b[N];
int n,k,t,cas=;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
int i=,j=;
a[]=b[]=;
while(a[i]<n)
{
i++;
a[i]=b[i-]+; //b[i-1]是由a[0]...a[i-1]组成的自大的数,所以b[i-1]+1不能用a[0]……a[i-1]组成
while(a[j+]*k<a[i])
j++;
if(a[j]*k<a[i]) //要求b[j],表示a[0]……a[i]组成,那么显然是要用到a[i]的,不然不就成了b[i-1],既然用了a[i],但是又要使相邻的倍数在K以上。则找到最大的j,使a[j]*k<a[i]那么满足条件,便是a[0]……a[j]能组成的最大的数,加上a[i]
b[i]=b[j]+a[i];
else
b[i]=a[i]; //当前项不能和之前项组合,那么最大的数就只能是本身 }
printf("Case %d: ",++cas);
if(a[i]==n)
puts("lose");
else
{
int ans;
while(n)
{
if(n>=a[i])
{
n-=a[i];
ans=a[i];
}
i--;
}
printf("%d\n",ans);
}
}
return ;
}

32MS

 #include<stdio.h>
#include<cstdlib>
int a[];
int main()
{
int t,ti=;
scanf("%d",&t);
while(t--)
{
int n,m,i,k=;
scanf("%d%d",&n,&m);
a[]=;
bool flag=;
for(i=;a[i]<=n;i++)
{
if(a[i]==n) flag=;
while(a[k]*m<a[i]) k++;
a[i+]=a[i]+a[k];
}
if(flag) printf("Case %d: lose\n",ti++);
else
{
while(n!=a[i])
{
n%=a[i];
i--;
}
printf("Case %d: %d\n",ti++,n);
}
}
return ;
}

79MS

 #include<stdio.h>
#define N 2000000
int a[N],b[N];
int n,k,t,cas=;
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&k);
int i=,j=;
a[]=b[]=;
while(a[i]<n){
i++;
a[i]=b[i-]+;
while(a[j+]*k<a[i])
j++;
if(a[j]*k<a[i])
b[i]=b[j]+a[i];
else
b[i]=a[i];
}
printf("Case %d: ",++cas);
if(a[i]==n)
puts("lose");
else{
int ans;
while(n){
if(n>=a[i]){
n-=a[i];
ans=a[i];
}
i--;
}
printf("%d\n",ans);
}
}
return ;
}

47ms
看这组数据就会懂了:

这是把a[i]打出来了.......

Something about 博弈(POJ 3922 A simple stone game)的更多相关文章

  1. POJ 3922 A simple stone game

    题目: E - A simple stone game Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d &am ...

  2. hdu 2486/2580 / poj 3922 A simple stone game 博弈论

    思路: 这就是K倍动态减法游戏,可以参考曹钦翔从“k倍动态减法游戏”出发探究一类组合游戏问题的论文. 首先k=1的时候,必败态是2^i,因为我们把数二进制分解后,拿掉最后一个1,那么会导致对方永远也取 ...

  3. HDUOJ--------A simple stone game(尼姆博弈扩展)(2008北京现场赛A题)

    A simple stone game                                                                                  ...

  4. POJ 1740 A New Stone Game(博弈)题解

    题意:有n个石子堆,每一个都可以轮流做如下操作:选一个石堆,移除至少1个石子,然后可以把这堆石子随便拿几次,随便放到任意的其他石子数不为0的石子堆,也可以不拿.不能操作败. 思路:我们先来证明,如果某 ...

  5. HDU6237-A Simple Stone Game-找素因子(欧拉函数)-2017中国大学生程序设计竞赛-哈尔滨站-重现赛

    A Simple Stone Game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Ot ...

  6. POJ.3468 A Simple Problem with Integers(线段树 区间更新 区间查询)

    POJ.3468 A Simple Problem with Integers(线段树 区间更新 区间查询) 题意分析 注意一下懒惰标记,数据部分和更新时的数字都要是long long ,别的没什么大 ...

  7. 2017中国大学生程序设计竞赛-哈尔滨站 H - A Simple Stone Game

    A Simple Stone Game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Ot ...

  8. POJ 3468.A Simple Problem with Integers-线段树(成段增减、区间查询求和)

    POJ 3468.A Simple Problem with Integers 这个题就是成段的增减以及区间查询求和操作. 代码: #include<iostream> #include& ...

  9. HDU 6237.A Simple Stone Game-欧拉函数找素因子 (2017中国大学生程序设计竞赛-哈尔滨站-重现赛)

    A Simple Stone Game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Ot ...

随机推荐

  1. Android入门之文件系统操作(一)简单的文件浏览器

    版权声明:本文为博主原创文章,未经博主允许不得转载.       import java.io.File; import java.util.*; import android.app.Activit ...

  2. Python 下的数据结构实现

    既然采用了 Python 编程语言实现数据结构,就要充分发挥 Python 语言的语法特性. 参考<Python 算法教程><数据结构与算法 -- Python 语言描述>: ...

  3. 洛谷P3834 可持久化线段树(主席树)模板

    题目:https://www.luogu.org/problemnew/show/P3834 无法忍受了,我要写主席树! 解决区间第 k 大查询问题,可以用主席树,像前缀和一样建立 n 棵前缀区间的权 ...

  4. Building a Space Station(bfs)

    http://poj.org/problem?id=2031 题意:给出n个球的圆心坐标x,y,z, 半径r,若任意两球不相交,则在两球间建桥.问需建桥的最短距离是多少. 思路:建图,以两球间相差的距 ...

  5. Django day15 (二) csrf的 跨站请求伪造 与 局部禁用 , 局部使用

    一:  csrf 的跨站请求伪造 二: csrf 的局部禁用 , 局部使用

  6. IntelliJ IDEA/PyCharm/WebStorm 2019.1.2 注册码激活

    [IDEA2019.1.2最新版版本激活,直接查看底部] 网上IntelliJ IDEA激活方式大多均已失效,目前常用激活方式为License Server 激活: http://idea.imsxm ...

  7. python 进程理论基础

    背景知识 顾名思义,进程即一个软件正在进行的过程.进程是对正在运行的程序的一个抽象 进程的概念起源于操作系统,是操作系统的最核心的概念,也是操作系统提供的最古老的也是最重要的抽象概念之一.操作系统的其 ...

  8. 跳出双重for循环的案例__________跳出了,则不再执行标签ok下的for循环代码

    ok: for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { System.out.print("*" ...

  9. [hihocoder][Offer收割]编程练习赛50

    循环数组 计算a[i]的前缀和s[i],计算l[i]为1~i-1中最小的s值,r[i]为i~n中最大的s值. 则a[i]~a[n]满足性质的条件为r[i]-s[i-1]>0,a[1]~a[i-1 ...

  10. android黑科技系列——防自动抢红包外挂原理解析

    一.前言 春节过年发个红包本来就是为了讨个喜庆,朋友亲戚之间的关系交流,但是现在随着技术变革,抢红包插件越来越多,导致现在不太愿意发红包了,特别是在一个多人群里,潜水的非常多,但是丢个红包瞬间就没了, ...