取石子游戲
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 29247 | Accepted: 9575 |
Description
Input
Output
Sample Input
2 1 8 4 4 7
Sample Output
0 1 0
分析:這是威佐夫問題,學習了
轉自http://yjq24.blogbus.com/logs/42826226.html
大致上是這樣的:有兩堆石子,不妨先認為一堆有10,另一堆有15個,雙方輪流取走一些石子,合法的取法有如下兩種:
1)在一堆石子中取走任意多顆;
2)在兩堆石子中取走相同多的任意顆;
約定取走最后一顆石子的人為贏家,求必敗態(必勝策略)。
這個可以說是MR.Wythoff(Wythoff於1907年提出此游戲)一生全部的貢獻吧,我在一篇日志里就說完有點殘酷。這個問題好像被用作編程競賽的題目,網上有很多把它Label為POJ1067,不過如果學編程的人不知道Beatty定理和Beatty序列 ,他們所做的只能是找規律而已。不熟悉的人可以先在這里 玩幾局~
簡單分析一下,容易知道兩堆石頭地位是一樣的,我們用余下的石子數(a,b)來表示狀態,並畫在平面直角坐標系上。
用之前的定理: 有限個結點的無回路有向圖有唯一的核 中所述的方法尋找必敗態。先標出(0,0),然后划去所有(0,k),(k,0),(k,k)的格點;然后找y=x上方未被划去的格點,標出(1,2),然后划去(1,k),(k,2),(1+k,2+k),同時標出對稱點(2,1),划去(2,k),(1,k),(2+k,1+k);然后在未被划去的點中在y=x上方再找出(3,5)。。。按照這樣的方法做下去,如果只列出a<=b的必敗態的話,前面的一些是(0,0),(1,2),(3,5),(4,7),(6,10),…
接下來就是找規律的過程了,忽略(0,0),記第n組必敗態為(a[n],b[n])
命題一:a[n+1]=前n組必敗態中未出現過的最小正整數
[分析]:如果a[n+1]不是未出現的數中最小的,那么可以從a[n+1]的狀態走到一個使a[n+1]更小的狀態,和我們的尋找方法矛盾。
命題二:b[n]=a[n]+n
[分析]:歸納法:若前k個必敗態分別為 ,下證:第k+1個必敗態為
從該第k+1個必敗態出發,一共可能走向三類狀態,從左邊堆拿走一些,從右邊堆拿走一些,或者從兩堆中拿走一些.下面證明這三類都是勝態.
情況一:由命題一,任意一個比a[k+1]小的數都在之前的必敗態中出現過,一旦把左邊堆拿少了,我們只要再拿成那個數相應的必敗態即可。
情況二(從右邊堆拿走不太多):這使得兩堆之間的差變小了,比如拿成了 ,則可再拿成
;
情況二(從右邊堆拿走很多):使得右邊一堆比左邊一堆更少,這時類似於情況一,比如拿成了 (其中a[m] ;
情況三:比如拿成 ,則可再拿成
.
綜上所述,任何從 出發走向的狀態都可以走回核中.故原命題成立.
以上兩個命題對於確定(a[n],b[n])是完備的了,給定(0,0)然后按照這兩個命題,就可以寫出(1,2),(3,5),(4,7),…
這樣我們得到了這個數列的遞推式,以下我們把這兩個命題當成是(a[n],b[n])的定義。
先證明兩個性質:
性質一:核中的a[n],b[n]遍歷所有正整數。
[分析]:由命題一,二可得a[n],b[n]是遞增的,且由a[n]的定義顯然。
性質二:A={a[n]:n=1,2,3,…},B={b[n]:n=1,2,3,…},則集合A,B不交。
[分析]:由核是內固集,顯然。
看到這里大家有沒有想到Beatty序列呢,實際上a[n]和b[n]就是一個Beatty序列。
,有
,解方程
得 ,到此,我們找到了該必敗態的通項公式。
實際上這組Beatty序列還有一些別的性質,比如當一個數是Fibonacci數的時候,另一個數也是Fibonacci數;而且兩者的比值也越來越接近黃金比,這些性質在得到通項公式之后不難證明。
總的來說,這個問題給我們了哪些啟示呢?首先用定理所說的方法找核,然后給出核的規律(遞推,或是通項)並且證明。最后附上一張對應的必敗態圖.
轉自http://yjq24.blogbus.com/logs/42653430.html
上次說了勝態和必敗態,還記得最后的練習么?桌子上有15個石子,每人每次可以拿去1個或3個石子,拿走最后一個石子的人贏,列出所有的必敗態:0,2,4,6,8,10,12,14。說過了狀態作為結點可以畫一張有向圖,下面這張圖就是這個游戲所對應的:
定理:有限個結點的無回路有向圖有唯一的核。
證明:核可以用如下的方式找出:首先找出沒有后繼結點的點集P[1](最基本的必敗態,比如上圖中的結點0),然后找到那些指向P[1]的結點集合為N[1](最基本的勝態,比如上圖的結點1和結點3);然后,除去P[1]和N[1]中的點並除去和這些點關聯的邊,繼續尋找沒有后繼結點的點集P[2](更高級的必敗態,比如上圖中的結點2),依次類推,則最后的核為P=P[1]並P[2]並…並P[n]。
很容易說明如此找到的核是內固集,也是外固集,滿足核的定義,下面說明一下核為什么不是空集:實際上P[1]就不是空集,對一個沒有回路的有向圖來說,從圖上的某一點出發,就無法回到原來到過的點。而圖中的點又是有限的,所以最后必將在某個結點終止,故P不是空集。
針對不同的游戲,找核是一個麻煩事。首先生成圖,有向邊取決於游戲規則,然后當我們要找某個必敗態的時候,是要先找到之前所有的必敗態的,而這正是一個數學問題和一個編程問題的關鍵差別。在立方和分解問題[unsolved]中,我的問題的提法都是針對某一個特定輸入的n來看是否存在(x,y)滿足立方和或者平方和等於n.實際上,如果提法換成,輸出對所有不大於n的數中可以被分解的數,那么這種提法更適合計算機去解決,因為本質上來說,兩個問題是不一樣的。對於前者我只需要知道有關n的情況就可以了,而對后者,卻調動了資源去計算所有不大於n的數的情況。雖然他們看起來很相近,但是從道理上來說應該后者的勞動量要大得多,可悲的事情就在於,有時候你要算出n的情況,就不得不算一些比n小的數的情況,而這個計算的數目通常是隨着n增大而增大的;另一個可悲的事情是,程序員往往已經習慣了第二種提問方式。數學家希望找到某些必要條件或者充分條件來確定n能否被分解,同樣的道理,我們也希望能直接找到必敗態的規律,而不真正依賴於象上述定理那樣遞歸的思想從P[1]開始找起,這樣來解決問題。
但是,必敗態的規律是嚴格依賴於規則的,這一點對找出必敗態的規律來說造成了很大的局限性。這個圖的模型在以后還會遇到,到時有更好的方法來尋找必敗態。
轉自http://yjq24.blogbus.com/logs/42304551.html
高斯取整函數又叫向下取整函數,常見的記法如下: ,既然是向下取整,也就是說[-3.5]=-4,這個取整對負數來說就不是簡單地扔掉小數部分,這是要注意的。可以說,高斯取整是聯系連續和離散的重要橋梁。
小知識:高斯函數性質
1) x-1<[x]<=x<[x]+1
2) [x+n]=[x]+n,(n為整數)
3) [x]+[y]<=[x+y]<=[x]+[y]+1 //左邊由性質2易證,右邊利用[x+y]<=x+y<[x]+[y]+2
4) [nx]>=n[x],(n為正整數) //反復利用性質3左邊
5) [x/n]=[[x]/n],(n為正整數)
// 換元后等價於證[ny]/n-1<[y]<=[ny]/n,右邊由性質4易證,左邊有 [ny]/n<=[y]+{y}<[y]+1
歐拉給出過一個很經典的多項式: ,該多項式在n=0,1,2,…,39時產生40個素數。利用高斯取整函數,可以做 一件差不多的事:
,這個函數跳過所有的平方數,而且值域覆蓋所有非完全平方數構成的集合,有了上面的這些性質作武器,證明並不難,這里就略去了。
今天的主題還是 Beatty定理 :
正無理數 滿足
, 則數列
;
嚴格遞增, 並且這兩個數列構成Z+上的一個分划(也就是它們無交地遍歷全體正整數)。
[題解]:
其實作為習題是不難的,顯然 ,於是
,故
Step1.先證明兩數列不交:[反證]若 ,有
,即有
,
兩式相加:得k<m+n<k+1,這和m,n,k都是自然數矛盾;
Step2.再證兩數列能取遍所有的正整數:[反證]若k不在 中,則有
於是
兩式分別除以 和
后相加:得
,這和m,n,k都為自然數矛盾.
證畢.
由Beatty定理得到的兩個數列稱為互質數列,不過別被名稱所欺騙,a[n]和b[n]並不能保證對應互質。
//再繼續看看必敗點
//看完上面的有了點了解吧,代碼如下:
#include<iostream> #include<cmath> using namespace std; int main () { int a,b,dif; double p=(sqrt((double)5)+1)/double(2); while(cin>>a>>b) { dif=abs(a-b);//取差值 a=a<b?a:b;//取較小的值 if(a==(int)(p*dif))//判斷是不是奇異局勢 printf("0\n"); else printf("1\n"); } return 0; }
該類問題另一種表述
移動的皇后
輸入包含若干行,表示若干種皇后的初始情況,其中每一行包含兩個非負整數a和b,表示皇后的初始坐標,a和b都不大於1,000,000,000。
輸出對應也有若干行,每行包含一個數字1或0,如果最后你是勝者,則為1,反之,則為0。
8 4
4 7
1
0