[POJ2505]A multiplication game(博弈)

29 篇文章 0 订阅

题目描述

传送门
129>=n
PoA
PoPo_Po
...
题意:起始数为1,每次可以将这个数乘2或乘9,首先得到>=n的数的人获胜。问是否有必胜策略。

题解

这道题我用了一个非常奇怪的方法。
当n<=18的时候随便讨论一下就行了。来看n>18的情况。
首先我们将n分解为 18kx 的形式(x有可能为实数)。
1、当x=1的时候,先手必败。因为无论先手选择2还是9,后手都可以选择另一个数将其凑成18.
2、当x>9的时候,先手必败。同样无论先手选择2还是9,后手都可以选择另一个数将其凑成18。而最后凑不成整18的那个数,先手无论选2还是选9都会帮助后手取得胜利。
3、当x<=2的时候,先手必胜。因为先手可以先选一个2,然后无论后手怎么选,都选另一个数来凑成18。
4、当 2<x<=9 的时候,是最麻烦的一种情况。后手不会傻到每一次都给先手去凑18,所以一定是先手先选择一个数,然后根据后手的选择来凑18,但是先手唯一担心的就是这个过程中自己还没有凑到18后手就用一个数和先手选择的第一个数组合然后超过n了。我们可以发现9是2的4.5倍。当 2<x<=4.5 的时候,如果先手先选择了2,那么后手只需要每次都选择2就可以保证即使先手选9也拿不到n,在这个过程中如果先手选择了2那么权利反转,同样是先手必败;如果先手先选择了9,那么后手只需要也选择9,然后根据先手的选择凑18,就可以保证最后的胜利。当 4.5<x<=9 的时候,先手只需要先选择9,然后根据后手的选择凑18,这样无论如何后手怎样选都无法在没凑到18的情况下达到n,此时先手必胜。

代码

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

double n;
const double mi=18.0;

int main()
{
    while (~scanf("%lf",&n))
    {
        if (n<mi)
        {
            if (n<=9) puts("Stan wins.");
            else puts("Ollie wins.");
            continue;
        }
        double p;
        for (p=1.0;;)
            if (p*mi>n) break;
            else p*=mi;
        double t=n/p;
        if (t==1) puts("Ollie wins.");
        else if (t>9) puts("Ollie wins.");
        else if (t<=2) puts("Stan wins.");
        else if (t<=4.5) puts("Ollie wins.");
        else puts("Stan wins.");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值