http://acm.hdu.edu.cn/showproblem.php?pid=3389
題意:
有N堆石子,每堆石子都有一定的石子數,Alice和Bob輪流玩一個遊戲,遊戲的規則是,每回合一個人可以選擇1-n堆石子中的某一堆進行操作,操作是:假設選擇操作的那堆石子的編號爲A,現在還要選擇一堆石子B,滿足B<A && (A+B)%2==1 && (A+B)%3==0,然後可以將A中至少一顆石子移到B中去,第一個不能進行合法操作的人輸,問誰能贏。
思路:
這是一個階梯博弈的題目,首先我們可以發現,只有1 ,3 ,4 三個數是沒有前綴的, 也就是terminal狀態,其餘的每個狀態我們都可以計算出每個編號到這幾個terminal的步數(當然有的編號的步數並不唯一,但是奇偶性是唯一的)。接下去我們就會發現,每次從一個奇數步的點,一定是要移到到 一個偶數步的點上去,也就是說每次只能移到奇數步,這個通過編號自身的奇偶性就可以證明了。這樣就轉化爲了階梯博弈的類型了,我們只需要關注奇數步編號出的石子的數量就可以了,如果奇數步編號處的石子的Nim和爲0,則必敗,不爲0則必勝。接下去我們就簡單地證明一下這個策略:如果移動的是奇數步位置的石子,則一定是移動到偶數步的位置,這時候我們只需要按照Nim博弈的必勝策略進行遊戲就可以贏;如果移動的是偶數步數編號位置的石子,則移動是移動到奇數步的位置,這時候我們只需要將剛剛移動過來的石子移動到下一個偶數步位置,原來的Nim局面並沒有變化,變化的只是偶數步石子的數量。這樣我們就證明了原遊戲可以轉化爲Nim遊戲。
代碼:
#include <stdio.h>
#include <string.h>
int main(){
int T , N ,a ;
scanf("%d",&T) ;
int cas = 0 ;
while( T-- ){
scanf("%d",&N);
int res = 0 ;
for(int i=0;i<N;i++){
scanf("%d",&a);
if( i%6==1 || i%6==4 || i%6 ==5){
res ^= a ;
}
}
if( res ) printf("Case %d: Alice\n",++cas);
else printf("Case %d: Bob\n",++cas) ;
}
return 0 ;
}