【hdu 2486】A simple stone game
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的更多相关文章
- 【hdu 5996】dingyeye loves stone
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s) ...
- 【HDU 5399】Too Simple
题 Description Rhason Cheung had a simple problem, and asked Teacher Mai for help. But Teacher Mai th ...
- 【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 ...
- 【数位dp】【HDU 3555】【HDU 2089】数位DP入门题
[HDU 3555]原题直通车: 代码: // 31MS 900K 909 B G++ #include<iostream> #include<cstdio> #includ ...
- 一本通1548【例 2】A Simple Problem with Integers
1548:[例 2]A Simple Problem with Integers 题目描述 这是一道模板题. 给定数列 a[1],a[2],…,a[n],你需要依次进行 q 个操作,操作有两类: 1 ...
- 【HDU 5647】DZY Loves Connecting(树DP)
pid=5647">[HDU 5647]DZY Loves Connecting(树DP) DZY Loves Connecting Time Limit: 4000/2000 MS ...
- -【线性基】【BZOJ 2460】【BZOJ 2115】【HDU 3949】
[把三道我做过的线性基题目放在一起总结一下,代码都挺简单,主要就是贪心思想和异或的高斯消元] [然后把网上的讲解归纳一下] 1.线性基: 若干数的线性基是一组数a1,a2,a3...an,其中ax的最 ...
- 【HDOJ 5399】Too Simple
pid=5399">[HDOJ 5399]Too Simple 函数映射问题 给出m函数 里面有0~m个函数未知(-1) 问要求最后1~n分别相应仍映射1~n 有几种函数写法(已给定的 ...
- 【HDU 2196】 Computer(树的直径)
[HDU 2196] Computer(树的直径) 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 这题可以用树形DP解决,自然也可以用最直观的方法解 ...
随机推荐
- php数组函数(分类基本数组函数,栈函数,队列)
php数组函数(分类基本数组函数,栈函数,队列函数) 一.总结 1.常用数组函数 函数 描述 array() 创建数组. array_combine() 通过合并两个数组来创建一个新数组. array ...
- HTML的SEO(搜索引擎优化)标准
HTML的SEO(搜索引擎优化)标准 一.总结 这个做seo的时候要多看,做网站优化的时候 1. SEO(搜索引擎优化):通过总结搜索引擎的排名规律,对网站进行合理优化,使你的网站在百度和Google ...
- 早该知道的 7 个JavaScript 技巧[转]
简洁写法 对象的简写在过去,如果你想创建一个对象,你需要这样: var car = new Object(); car.colour = 'red'; car.wheels = 4; car.h ...
- React组件之间通过Props传值的技巧(小案例,帮助体会理解props、state、受控组件和非受控组件等)
本文重要是根据react小书上的一个很简单的例子改编的,加上自己的学习理解,希望可以通过实际案例让大家对概念有更清晰的理解,当然也希望能一块学习. import React,{Component} f ...
- json问题小结
json 键值对增加.删除 obj.key='value'; // obj.key=obj[key]=eval("obj."+key); delete obj.key; vue中新 ...
- finalkeyword对JVM类载入器的影响
众所周知,当訪问一个类的变量或方法的时候.假设没有初始化该类.就会先去初始化一个类 可是,当这个类的变量为final的时候,就不一定了 请看以下的样例 package com.lala.shop; i ...
- ios 推断是qq,银行卡,手机号等等公用的方法。
#import <Foundation/Foundation.h> typedef enum { IdentifierTypeKnown = 0, IdentifierT ...
- vue项目在其他电脑运行报错
解决方法1.先删除node_modules文件夹2.$ cnpm cache clean 命令清除掉cache缓存3.cnpm install4.npm run dev
- FZU Problem 2062 Suneast & Yayamao
http://acm.fzu.edu.cn/problem.php?pid=2062 题目大意: 给你一个数n,要求求出用多少个数字可以表示1~n的所有数. 思路: 分解为二进制. 对于一个数n,看它 ...
- Haproxy 为 mysql 做负载均衡
.tar.gz cd haproxy- uname -r vim /etc/haproxy.cfg global #日志 log 127.0.0.1 local0 maxconn chroot /tm ...