Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 592 Accepted Submission(s): 341

Problem 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

【题目链接】:http://acm.hdu.edu.cn/showproblem.php?pid=2486

【题解】

/*
首先分类讨论一下;
①k=1
则除了2^i之外,都是先手赢;
先手可以进行如下的策略;
把剩余的石子的数目转换成二进制;
先手每次可以把二进制表示的最后一个1给删掉;
比如6的二进制110
则减去2
->100
这时对方是没办法减去这一个1的,因为对方不能取的比你大(k=1)
所以对方只能取1或2
如果取1的话
->011
你还是按照一样的策略每次取最后一个1;
对方还是不能取倒数第二个1;
....
"所以你总是能取最后一个1。"
也即你能赢.
取2同理
总之你只要每次都取最后一个1表示的数,则你总是可以赢;
当然如果是2^i,则你不能取走仅有的一个1;
只能减去1..2^i-1中的任意一个数字;
如果你取到只剩下2^(i-1)以下,则对方直接赢了(对方最多可以取2^(i-1)个);
但是如果你取到剩下2^(i-1)以上;
那二进制形式里面必然还剩下2个以上的1;
则对方可以用上述策略击败你;(每次取最后一个1);
②k=2
则除非n为斐波那契数列的某一项,否则先手一定赢;
(1,2,3,5,8,13...)
有性质:任意一个整数x总能分解成若干项不相邻的斐波那契数列的和;
(这里的整数x是不属于斐波那契数列中的任意一项的整数);
且有f[i+2]>2*f[i];
那么如果一个整数不是斐波那契数列
比如12=1+3+8
则可以把它类比成二进制的形式111
我们还是每次取走最后一个1;
这里的1代表的是1;
就变成110
但是对方是没办法取走倒数第二个1的
因为f[i+2]>2*f[i];(任意一个整数可以由不相邻的斐波那契数相加构成)
这就说明在对方可取的范围里面不足以减去第二个1;
对方只能把倒数第二个1拆掉;
这样可以保证总是你取走最后一个1;
所以你总是能够赢.
相应的如果你面临了斐波那契数列
则你必须把那唯一的一个1拆掉(类似二进制);
则对方可以任意地拆掉你留给它的最后的一个1;
然后让你面临尴尬的局面。balabala
③k>2
我们考虑构造像k=2的那总数列a;
设我们已经构造到数列a第的i项a[i]了,且1..b[i](内除了这个数列的元素)
都能由若干个数列ai的元素构成且它们相邻之间a[xn]/a[xn-1]>k
那么有a[i+1]=b[i]+1;
因为b[i]+1这个元素没办法由1..a[i]构造成;
所以只能新加这么一项了;
然后要求b[i+1]了;
显然b[i]+1..b[i+1]内这些数的构成都要a[i+1]参与;
现在的问题是要给a[i+1]寻找"合作的伙伴";
显然那些合作伙伴的下标t;
要满足k<a[i+1]/a[t];
可以维护这么一个t值(因为a[i]是单调递增的,所以很好维护的);
则b[i+1]=a[i+1]+b[t];
(1..b[t]都是能用不超过a[t]的项构成的(它们之间的倍数关系大于k))
如果不存在t的话b[i+1]=a[i+1]=b[i]+1;
最后看看n在不在a数列中,不在的话先手赢,否则先后输;
具体原因上面已经讨论过了(都是类比二进制);
(k=1、2的情况都能归结到这种情况);
是先手赢的话一直减a数列中的数(从大到小能减就减);
最小的那个数字肯定就是我们上面一直讨论的"数字1"了;
你把它输出就好;
最坏情况是n=1e8,k=1e5
看看数列的长度是多少就可以了;(作为数列的size);
*/

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%I64d",&x) typedef pair<int,int> pii;
typedef pair<LL,LL> pll; const int MAXN = 1000000;
const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0); int T;
LL n,k;
LL a[MAXN],b[MAXN]; int main()
{
//freopen("F:\\rush.txt","r",stdin);
int ii = 0;
for (rei(T);T--;)
{
ii++;
rel(n);rel(k);
a[1] = b[1] = 1;
LL i = 1,t = 0;
while (a[i]<n)
{
i++;
a[i] = b[i-1]+1;
while (a[t+1]*k < a[i]) t++;
if (a[t]*k<a[i])
b[i] = a[i] + b[t];
else
b[i] = a[i];
}
printf("Case %d: ",ii);
if (a[i]==n)
puts("lose");
else
{
int ans = -1;
rep2(j,i-1,1)
if (n>=a[j])
{
n-=a[j];
ans = a[j];
}
printf("%d\n",ans);
}
}
return 0;
}

【hdu 2486】A simple stone game的更多相关文章

  1. 【hdu 5996】dingyeye loves stone

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s) ...

  2. 【HDU 5399】Too Simple

    题 Description Rhason Cheung had a simple problem, and asked Teacher Mai for help. But Teacher Mai th ...

  3. 【HDU 1757】 A Simple Math Problem

    题 Description Lele now is thinking about a simple function f(x). If x < 10 f(x) = x. If x >= 1 ...

  4. 【数位dp】【HDU 3555】【HDU 2089】数位DP入门题

    [HDU  3555]原题直通车: 代码: // 31MS 900K 909 B G++ #include<iostream> #include<cstdio> #includ ...

  5. 一本通1548【例 2】A Simple Problem with Integers

    1548:[例 2]A Simple Problem with Integers 题目描述 这是一道模板题. 给定数列 a[1],a[2],…,a[n],你需要依次进行 q 个操作,操作有两类: 1 ...

  6. 【HDU 5647】DZY Loves Connecting(树DP)

    pid=5647">[HDU 5647]DZY Loves Connecting(树DP) DZY Loves Connecting Time Limit: 4000/2000 MS ...

  7. -【线性基】【BZOJ 2460】【BZOJ 2115】【HDU 3949】

    [把三道我做过的线性基题目放在一起总结一下,代码都挺简单,主要就是贪心思想和异或的高斯消元] [然后把网上的讲解归纳一下] 1.线性基: 若干数的线性基是一组数a1,a2,a3...an,其中ax的最 ...

  8. 【HDOJ 5399】Too Simple

    pid=5399">[HDOJ 5399]Too Simple 函数映射问题 给出m函数 里面有0~m个函数未知(-1) 问要求最后1~n分别相应仍映射1~n 有几种函数写法(已给定的 ...

  9. 【HDU 2196】 Computer(树的直径)

    [HDU 2196] Computer(树的直径) 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 这题可以用树形DP解决,自然也可以用最直观的方法解 ...

随机推荐

  1. (cocos2d-js游戏)測试你的反应速度----------基本逻辑(上)

    游戏玩法:点击開始游戏.等待一个随机时间.然后背景颜色会变(在t1时刻),这时候你须要点击屏幕(在t2时刻),游戏结束.你的反应时间就是天t2-t1. 游戏逻辑: 游戏逻辑非常easy,如上图所看到的 ...

  2. Flume Source官网剖析(博主推荐)

    不多说,直接上干货! 一切来源于flume官网 http://flume.apache.org/FlumeUserGuide.html Flume Sources Avro Source Thrift ...

  3. 1.8 Python基础知识 - 数值类型

    一.int类型(任意精度整数) 整型类型(int)是表示整数的数据类型.与其他计算机语言有精度限制不同,Python的整数位数可以为任意长度位数(只受限制于计算机内存) 数字字符串即整型常量. pyt ...

  4. (转) 如何取消Linux下,vi中显示的^M符号

    转自:http://www.cnblogs.com/dkblog/archive/2012/02/03/2337187.html [背景知识] ^M 是ascii中的'\r', 回车符,是16进制的0 ...

  5. SQLite基础学习

    SQLite是一款轻量级数据库,集成于android中,以下从分享一下自己学习的. 在查阅资料时有一些好的说明就直接用了: 主要的curd语句 以下SQL语句获取5条记录,跳过前面3条记录 selec ...

  6. synchronized和AtomicInteger解决并发问题的性能比较

    AtomicInteger,一个提供原子操作的Integer的类.在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字.而volatile ...

  7. 【例题 6-14 UVA-816】Abbott's Revenge

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 预处理出某个方向的左边.前边.右边是哪个方向就好了. 然后就是普通的bfs了. hash存到某个点,走到这里的方向的最小距离. df ...

  8. ThinkPHP视图查询

    ThinkPHP视图查询 一.总结 1.这里的视图查询和多表查询很像,当然多表查询的话肯定要支持左右链接查询 2.view:视图的使用,关键字是view 3.sql视图功能支持:thinkphp支持视 ...

  9. OC学习篇之---文件的操作

    今天我们来介绍OC中文件操作,在之前的文章中,已经接触到了文件的创建了,但是那不是很具体和详细,这篇文章我们就来仔细看一下OC中是如何操作文件的: 第一.首先来看一下本身NSString类给我们提供了 ...

  10. hdu 5375 Gray code dp

    #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; cons ...