[POJ2505]A multiplication game(博弈)

来源:互联网 发布:python判断是否是str 编辑:程序博客网 时间:2024/05/17 06:58

题目描述

传送门
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.");    }}
0 0
原创粉丝点击