1. 程式人生 > >「POJ2505」A multiplication game [博弈論]

「POJ2505」A multiplication game [博弈論]

== 思路 相關 無語 兩個 scan n) include 區間

題目鏈接:http://poj.org/problem?id=2505

題目大意:

兩個人輪流玩遊戲,Stan先手,數字 p從1開始,Stan乘以一個2-9的數,然後Ollie再乘以一個2-9的數,直到誰先將p乘到p>=n時那個人就贏了,而且輪到某人時,某人必須乘以2-9的一個數。

解題思路:

這是一道博弈論的題目。
不過這道題並沒有用SG函數相關的知識。
首先我們可以很快判斷區間[2,9]必定是先手勝
然後緊接著是區間[10,18]區間是後手勝
然後是什麽呢?
[18,??]
我們可以這樣來理解:
我們可以考慮一下,先手是要取勝,就是要越大越好,越大越快,
所以每次輪到先手進行操作時,肯定是要乘上最大的哪一個數,也就是9
那麽我們反過來,後手就是要盡量拖住先手,所以每一次都會乘上哪一個最小的數,也就是2
於是,這樣的話我們就可以將區間補出來:
[2,9]
[9+1,9*2]
[9*2+1,9*2*9]
[9*2*9+1,9*2*9*2]
.......
所以著一道題我們就可以做了吧。
至於怎麽操作,我用的方法並不是最快的,但是應該是比較清楚的。
定義l,r為2,9然後按照上面模擬即可,然後每次判斷就行

額。。。網上有題解說他們是找規律找出來的,我連找規律都不會找。。。。。推了好久才推出來。。。
無語。。。
貼代碼:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 typedef long long ll;
 6 ll n;
 7 int main()
 8 {
 9     while(scanf("%lld",&n)==1)
10     {
11         ll l=2;
12         ll r=9;
13
int flag=1; 14 while(true) 15 { 16 if(n>=l&&n<=r) 17 { 18 if(flag==1) printf("Stan wins.\n"); 19 else printf("Ollie wins.\n"); 20 break; 21 } 22 else{ 23 l=r+1
; 24 if(flag==1) 25 { 26 r=r*2; 27 flag=0; 28 } 29 else 30 { 31 flag=1; 32 r=r*9; 33 } 34 } 35 } 36 } 37 return 0; 38 }

謝謝大家支持。

如何可以指出我有哪些寫得不好的地方,本人感激不盡!!

「POJ2505」A multiplication game [博弈論]