HDU 1517 && poj 2505 A Multiplication Game (基础博弈)

20 篇文章 1 订阅



A Multiplication Game

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2264    Accepted Submission(s): 1300

Problem 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

 

162
17
34012226
Sample Output

 

Stan wins.
Ollie wins.
Stan wins.

分析:
大致题意:Stan和Ollie玩相乘游戏,一开始Stan在1的基础上乘2~9的整数,然后轮到Ollie·····谁先将得数超过或等于所给的数,就算赢
思路分析:先来看看基本的规律
给的数为2~9 Stan wins
           10~18 Ollie wins
那下一个呢?
由上面可得:
9=9;
18=2×9;
就是Stan尽量小,而Ollie为了超过所给的数,尽量大
那数再大一点,超过了18,Ollie就没辙了
因为Stan取2,而Ollie最大取9,才只能到达18;那如果Ollie也取2,Stan取9也能到36
如果数再大一点,超过36,Stan也可以根据第一次的取值来增大后来的乘数
那也总有个值,Stan取不到吧。其实就是9(S)×2(O)×9(S)=162;
所以后面也就这样轮流寻找了
19~162 Stan wins   162=9×2×9;
163~324 Ollie wins   324=2×9×2×9;
 `````````````````
而且很有规律的,Stan和AOllie就这样交换着,我们可就这一点将所给的数重复除以18,将结果控制到18里来讨论
例如:19~162  除以18后,就是1.055556~9,正是在Stan赢的范围内,这里要用double做,因为用整数型的会去掉。。。
代码如下:
#include <iostream>
using namespace std;
typedef long long ll;
int main()
{
    double n;
    while(cin >> n)
    {
        while(n > 18)
            n /= 18;
        if(n <= 9) cout << "Stan wins." << endl;
        else cout << "Ollie wins." << endl;
    }
    return 0;
}
另一种理解方法,也蛮好的

如果输入是 2 ~ 9 ,(2~9)因为Stan 是先手,所以Stan 必胜
如果输入是 10~18 ,(9+1~9*2)因为Ollie 是后手,不管第一次Stan 乘的是什么,Stan肯定在 2 ~ 9 之间,如果Stan乘以 2 ,那么Ollie就乘以 9 ,就到18了,如果Stan乘以 9 ,那么Ollie乘以大于1的数都都能超过 10 ~ 18 中的任何一个数。Ollie 必胜
如果输入是 19 ~ 162,(9*2+1~9*2*9)那么这个范围是 Stan 的必胜态
如果输入是 163 ~ 324 ,(9*2*9+1~9*2*9*2)这是又是Ollie的必胜态
# include<stdio.h>
int main()
{
    double num;
    while(scanf("%lf",&num)!=EOF)
    {
        while(num>18)
        num/=18;
        if(num>9)
            printf("Ollie wins.\n");
        else
            printf("Stan wins.\n");
    }
    return 0;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值