博弈,枚举必胜区间______A multiplication game( poj 2505)

来源:互联网 发布:网络会员制营销好处 编辑:程序博客网 时间:2024/06/06 10:45

Description

Stan and Ollie play the game of multiplication by multiplying an integer p by one of the numbers 2 to 9. Stan always starts with p = 1, does his multiplication, then Ollie multiplies the number, then Stan and so on. Before a game starts, they draw an integer 1 < n < 4294967295 and the winner is who first reaches p >= n.

Input

Each line of input contains one integer number n.

Output

For each line of input output one line either 
Stan wins. 
or 
Ollie wins. 
assuming that both of them play perfectly.

Sample Input

1621734012226

Sample Output

Stan wins.Ollie wins.Stan wins.


题意:

每局游戏给出一个数字n,让p从1开始让两人轮流乘上一个2~9的整数,谁使得p最先大于等于p则胜利。


分析:其实这个题目得出答案很容易,枚举必胜区间即可:

显然,假如n为 [ 2, 9 ] 的时候,先手肯定赢。如果n为[10,18]的时候,后手肯定赢。

这个时候我们可以猜想,[ 19, X ] 一定是个先手必胜区间。X是多少呢?

我们先定义一个运算,Up(x) 表示对x进行向上取整,/ 表示浮点数除法意思就是带小数。

好我们回到刚才那个问题:因为第一次乘数的是先手,那么假如第一次乘的数为M ,则 Up(X/M) 一定处于后手必胜区。要想X最大,那么Up(X/M) = 18.所以M = 9,X = 18*9,所以当n为[ 19, 18 * 9 ] 时。先手一定可以乘上某个数使得Up(X/M)属于[ 10 , 18 ] .

这个时候我们可以看到规律。

[ 2 , 9 ] 先手

[ 10 , 18 ] 后手

[ 19 , 18 * 9 ] 先手

[ 18 * 9 + 1, 18 * 18 ] 后手

[ 18 * 18 + 1 , 18 * 18 * 9 ] 先手

[ 18 * 18  * 9 + 1, 18 * 18 * 18 ] 后手


所以对n一直除以18 直到小于等于18。如果n小于等于9就是先手,否则就是后手。


嗯答案得到了。如果我们想知道策略呢?

其实很简单

我们把先手区间定义为必胜区间,后手定义为必败区间。

如果我方是必胜方,每次我方乘数的时候,只需要使得自己乘数后的p 使得 Up(n/p)处于必败区间。就可以了。


其实这个问题可以和巴什博弈联系起来。巴什博弈是在一堆石子中,最多可以拿m个最少可以拿n个(n<=m),问先手还是后手赢。其实就是把加变为了乘。

解决的策略其实也是很相似的。



代码:

#include <iostream>  using namespace std;    int main(){      int n;      while(cin>>n){          while(n > 18){              n = n/18;          }          if(n <= 9)              cout << "Stan wins." << endl;          else              cout << "Ollie wins." << endl;      }      return 0;  }  



0 0
原创粉丝点击