今天無意中再群里看到有人在討論計(jì)算組合數(shù)的一種方法
感覺還有點(diǎn)用就記錄下來了 稍稍的證明了下 證明不是很嚴(yán)密,看官湊合著看吧
c(n,m) = n!/(m!*(n-m)!)
如果n和m比較大時(shí) 可能會(huì)導(dǎo)致中間超過數(shù)據(jù)范圍,不過我們可以直接用遞推也就是
c(n,m) = c(n-1,m)+c(n-1,m-1)
不過下面我們要用另外一種方法來計(jì)算這個(gè)組合
把分子和分母約掉之后就變成了
(n*(n-1)*……*(n-m+1))/m!
這樣上面和下面都是m個(gè)元素,我們可能會(huì)想到乘1個(gè)除1個(gè),這樣來避免越界,可是這樣會(huì)剛好整除嗎?不會(huì)出現(xiàn)小數(shù)使得最后的答案變錯(cuò)嗎?其實(shí)只要我們按照一定的順序來乘和除的話,是不會(huì)產(chǎn)生小數(shù)的,也就是說會(huì)一直整除的.下面給出我的簡單證明,如有錯(cuò)誤,還請指出(這個(gè)公式是借的這位博主的)
首先我們把上面那個(gè)分?jǐn)?shù)寫成這樣的
(n*(n-1)*……*(n-m+1))/(m*(m-1)*……*1)
這樣的話就相當(dāng)于n–>m (n-1)—>(m-1) …… (n-m+1)—>1
下面先給出主要程序吧
f = 1;//最后答案
for(i = 1;i <= m;i++)
f = f*(i+(n-m))/i;
現(xiàn)在主要的是要說明每次乘以(i+(n-m))然后再除以i不會(huì)產(chǎn)生小數(shù),我是這么想的,說先i是1,肯定不會(huì)有小數(shù),然后i=2,但是分母已經(jīng)乘過兩個(gè)數(shù)了,肯定有一個(gè)奇數(shù),一個(gè)偶數(shù),也不會(huì)產(chǎn)生小數(shù),同理3的時(shí)候也不會(huì),但是4的時(shí)候可能會(huì)這樣想,前面某個(gè)數(shù)k整除4,那已經(jīng)別2除掉了一個(gè)2,這樣會(huì)不會(huì)產(chǎn)生小數(shù)呢?結(jié)果是不會(huì)的,因?yàn)?個(gè)相當(dāng)于2個(gè)2,或者1個(gè)4,我們可以把除2的那個(gè)選擇到這4個(gè)當(dāng)中不能出4的那一個(gè)數(shù)上,這樣的話,就剩下了一個(gè)能整除4的了,然后其他的就和這里一樣了。
Fibonacci Nim是如下一種游戲
一堆石子有n顆.兩人按如下規(guī)則輪流取一定的石子。
1.第一個(gè)取的至少取1顆,至多取n-1顆
2.每次取的石子數(shù)不能超過對手剛?cè)〉?倍,最后取完的算贏家。
現(xiàn)在我們需要算出對于某個(gè)n,是先手必勝,還是后手必勝。看到題目,基本也就想到一二了,肯定和Fibonacci數(shù)列有關(guān),確實(shí)。不過怎么個(gè)有關(guān)法呢?相信只要你動(dòng)手算幾個(gè)小數(shù),就會(huì)猜出來了,對于n = Fi先手一定必?cái)?否則先手必勝。好了,下面我們就來證明這個(gè)結(jié)論吧:
首先我們會(huì)用到如下三個(gè)性質(zhì):
I.若K >= N,則狀態(tài)(N,K)必勝(在這里我們用(N,K)表示還剩下N顆石子,最多能取K顆石子的一個(gè)狀態(tài))
II.若狀態(tài)(N,N-1)先手必?cái)?那么狀態(tài)(N,K)(K<N)必?cái) ?/p>
III.若狀態(tài)(N,K)(K<N)則最后一次取走的石子數(shù)不超過2*N/3
下面證明(Fi,K)(K<Fi)必?cái)?/p>
一.F1(=2),F2(=3)顯然成立.
二.若F1至Fi成立,則F(i+1)成立
設(shè)先手取K顆石子。
1).若K>=F(i-1),后手得到狀態(tài)(N-K,2*K)(N=F(i+1)),2*K>=2*F(i-1)>F(i-1)+F(i-2)=F(i)>N-K.所以后手必勝,也就是先手必?cái) ?/p>
2).若K <= F(i-1)
我們可知(F(i-1),K)必?cái)?假設(shè)得到的),所以后手可以使先手達(dá)到(F(i),X)(X < F(i))狀態(tài)
由性質(zhì)III可得X <= (2*F(i-1)/3)*2 = 4*F(i-1)/3 = F(i-1)+1/2*F(i-1) <= F(i-1)+F(i-2)=F(i),所以(F(i),X)必?cái) ?/p>
下面是n != F(i)
那么(N,N-1)先手必勝。這要使得后手處于<=n的最大的Fibonacci數(shù)就行,這樣就相當(dāng)于后手必輸,也就是先手必勝。
Dynamic subtraction.
One can enlarge the class of subtraction games by letting the subtraction set depend on the last move of the opponent.Many early example sappear in Chapter12 of Schuh(1968).Here are two other examples.(For a generalization,see Schwenk(1970).) (a)There is one pile of n chips.The ?rst player to move may remove as many chips as desired,at least one chip but not the whole pile.There after,the players alternate moving,each player not being allowed to remove more chips than his opponent took on the previous move.What is an optimal move for the ?rst player if n =44?For what values of n does the second player have a win?
題目大意: 有一堆石子,個(gè)數(shù)為n,兩個(gè)人輪流,規(guī)則如下 第一個(gè)取石子的人至少取一個(gè),至多取n-1個(gè)。之后每個(gè)人不能比前一個(gè)人剛?cè)∵^的石子數(shù)多.沒得取了算輸,
對于這個(gè)我們對比較小的n歸納可知,如果n=2^k(k >=0)的話則是P態(tài),否則是N態(tài). 首先我們可以看到1是P態(tài)(先手無法取,因?yàn)椴荒苋⊥?,2是P態(tài)(只能取1個(gè),后手取剩下的一個(gè)) 所有的奇數(shù)都是N態(tài),因?yàn)槊看稳∫粋€(gè)的話,最后只剩下1顆石子的時(shí)候一定是由先手取,所以所有的奇數(shù)是N態(tài). 如果是偶數(shù)的話,第一次取的石子數(shù)不能超過一半,而且必須取偶數(shù).如果取奇數(shù)個(gè)的話,則后手變成了N態(tài),如果取超過一半的石子數(shù)的話,那么后手可以一次取完.先手也輸了. 所以4是P態(tài) 6只能取2,然后后手達(dá)到4這個(gè)P態(tài),所以先手必輸。 下面我們證明當(dāng)n = 2^k時(shí)為P態(tài), 首先i = 0,1,2時(shí)結(jié)論成立。現(xiàn)在假設(shè)n = 2^i(i>=1)時(shí)結(jié)論成立,令j = i+1;m = 2^j; 我們知道先手第一次取的石子數(shù)一定是小于2^i次的,而且從2^j到2^i和2^i到2^j是一樣多的數(shù)目. 于是我們可以看成先手可不可能通過取走一些石子使得后手處于2^i.其實(shí)這樣是不可能的,分析如下: 我們把2^j到2^i這些數(shù)都同時(shí)減去2^i,我們得到2^i,2^i-1,……,1,0,這樣就變成了一個(gè)2^i的取石子游戲了.我們可以知道在這里先手是必輸?shù)?本文如沒有特殊說明,則意味著兩個(gè)選手都按最優(yōu)的方案執(zhí)行)。首先我們得到2^(i-1)次,如果先手取的石子數(shù)比這個(gè)多的話,那么后手可以取走一定的數(shù)目使得先手處于2^i這個(gè)P態(tài).也就是說先手必輸,如果先手取走的數(shù)目比2^(i-1)少的話,那么可以得到取完2^j到2^i+1這個(gè)2^i個(gè)的時(shí)候先手也是必輸?shù)?也就是說在這個(gè)過程中后手同樣可以使得先手處于2^i這個(gè)P態(tài),這樣的話先手必輸,所以無論先手怎樣取石子,對于n=2^k(k>=0)必輸。 這樣的話,易知對于n != 2^k(k>=0)的先手必勝。
下面我們以一種游戲的方式來引進(jìn)三種基本的博弈問題。
一.巴什博奕(Bash Game):
首先我們來玩一個(gè)比較古老的報(bào)數(shù)游戲。A和B一起報(bào)數(shù),每個(gè)人每次最少報(bào)一個(gè),最多報(bào)4個(gè)。輪流報(bào)數(shù),看誰先報(bào)到30.
如果不知道巴什博弈的可能會(huì)覺得這個(gè)是個(gè)有運(yùn)氣成分的問題,但是如果知道的人一定知道怎樣一定可以贏。
比如A先報(bào)數(shù)的話,那么B一定可以贏(這里假定B知道怎么正確的報(bào)數(shù))
B可以這樣報(bào)數(shù),每次報(bào)5-k(A)個(gè)數(shù),其中k(A)是A報(bào)數(shù)的個(gè)數(shù)這樣的話沒一次
兩人報(bào)完數(shù)之后會(huì)變成5 10 15 20 25 30這樣是不是B一定會(huì)贏呢?是不是有一種被欺騙的感覺呢?好吧下面我們來看看這個(gè)原理。我們先看下一個(gè)一眼就能看出答案的例子 比如說我們報(bào)到5(4+1),每次報(bào)最多報(bào)4個(gè),最少報(bào)1個(gè).那么是不是后者一定可以贏呢?答案是肯定的。好了到這巴什博弈的精髓基本就OK了。
那么如果我們要報(bào)到n+1,每次最多報(bào)n個(gè),最少報(bào)1個(gè)的話,后者一定能夠贏。
現(xiàn)在我們需要報(bào)數(shù)到n,而每次最多報(bào)數(shù)m個(gè),最少報(bào)數(shù)1個(gè).我們可以化成這樣
n = k*(1+m)+r(0 <= r <= m)這樣的話如果r不等于0那么先手一定會(huì)贏,為什么呢?首先先手報(bào)r個(gè),那么剩下k倍(1+m)個(gè)數(shù),那么我們每次報(bào)數(shù)1+m-k(B)個(gè)數(shù)就一定能保證最后剩下1+m個(gè),那么就到了上面我們說的那個(gè)了,先手就一定會(huì)贏,如果r=0那么后手一定會(huì)贏,道理一樣的。
到這巴什博弈也就介紹完了,知道這個(gè)道理之后我們也可以去騙小朋友了。-_-//
二.威佐夫博奕(Wythoff Game):
這種博弈比前面一種要稍微復(fù)雜一點(diǎn)。我們來看下下面這個(gè)游戲。
有兩堆火柴棍,每次可以從某一堆取至少1根火柴棍(無上限),或者從兩堆取相同的火柴棍數(shù)。最后取完的是勝利者。好了,如果你不知道這個(gè)博弈定理,對于小數(shù)目的火柴棍數(shù),可能還能推出來,但是如果火柴棍數(shù)一多,就不行了。看了下面的這個(gè)介紹,你也會(huì)有一種被騙的感覺。
首先我們知道兩堆火柴是沒有差別的,也就是說第一堆有a根,第二堆有b根和第一堆有b根,第二堆有a根是一樣的結(jié)果。
我們用一個(gè)二維的狀態(tài)(a,b)來記錄當(dāng)前剩下的火柴數(shù),表示第一堆剩下a根火柴,第二堆剩下b根火柴。同樣我們假設(shè)兩個(gè)人的編號是A和B,且A先取。
那么如果某個(gè)人遇到了這樣的狀態(tài)(0,0)那么也就是說這個(gè)人輸了。這樣的狀態(tài)我們叫做奇異狀態(tài),也可以叫做失敗態(tài)。
那么接下來的幾個(gè)失敗態(tài)為(1,2),(3,5),(4,7),(6,10),(8,13)……
我們用a[i]表示失敗態(tài)中的第一個(gè),b[i]表示失敗態(tài)中的第二個(gè).(i從0開始).
那么我們可以看到b[i] = a[i]+i;(i >= 0),a[i]是前面的失敗態(tài)中沒有出現(xiàn)過的最小的整數(shù)
下面我們可以得到三個(gè)基本的結(jié)論。
1.每個(gè)數(shù)僅包含在一個(gè)失敗態(tài)中
首先我們知道a[k]是不可能和前面的失敗態(tài)中的a[i],b[i]重復(fù)的(這點(diǎn)由a[i]的得到可以知道)
b[k] = a[k]+k > a[k-1]+k>a[k-1]+k-1+1>a[k-1]+(k-1) = b[k-1]>a[k-1]這樣我們知道每個(gè)數(shù)僅在一個(gè)失敗態(tài)中。
2.每個(gè)失敗態(tài)可以轉(zhuǎn)到非失敗態(tài)。
加入當(dāng)前的失敗態(tài)為(a,b),那么如果我們只在一堆中取的話,肯定會(huì)變成非失敗態(tài)(這點(diǎn)由第一點(diǎn)可以保證),如果從兩堆同時(shí)取的話,由于每個(gè)失敗態(tài)的差是不一樣的,所以也不可能得到一個(gè)失敗態(tài)。也就是說一個(gè)失敗態(tài)不管你怎么取,都會(huì)得到一個(gè)非失敗態(tài)。
3.每個(gè)非失敗態(tài)都可以轉(zhuǎn)到一個(gè)失敗態(tài)
對于這個(gè)結(jié)論,首先我們要知到每個(gè)狀態(tài)(a,b)要么a = a[i],要么b = b[i].(每個(gè)數(shù)都出現(xiàn)在一個(gè)失敗態(tài)中),下面我們分兩種情況來討論
I.a = a[i].如果b = a的話那么一次取完就變成了(0,0).如果b > b[i]的話,那么我們從第二堆中取走b-b[i]就變成了一個(gè)失敗態(tài)。如果b < b[i].那么我們從兩堆中同時(shí)取走a-a[b-a[i]]這樣得到失敗態(tài)(a[b-a[i]],a[b-a[i]]+b-a[i])(a[i] = a)
II.b = b[i].如果a > a[i]那么我們從第一堆中取走a-a[i]根火柴.
如果a < a[i].這里又分兩種情況。第一是a = a[k](k < i)
那么我們從第二堆取走b - b[k]就行了。
第二是a = b[k]這樣的話由于兩堆火柴是沒有區(qū)別的,所以我們把b變成a[k]就行了,也即是從第二堆火柴中取走b - a[k]就變成了失敗態(tài)
至于怎么判斷一個(gè)狀態(tài)是否是失敗態(tài).我們可以用下面的方法來判斷(本人暫時(shí)還不會(huì)證明)
a[i] = [i*(1+√5)/2](這里的中括號表示向下取整) b[i] = a[i]+i;
那么這就是一個(gè)失敗態(tài),
看了這之后可以去找POJ1067練練手
三.尼姆博奕(Nimm Game):
這個(gè)已經(jīng)變成了三堆火柴了。每次只能從某一堆取任意個(gè)(至少為1),最后取完的為勝利者。
這個(gè)博弈我們用三維的狀態(tài)來表示(a,b,c).對于每個(gè)失敗態(tài)我們有a^b^c = 0至于為什么我暫時(shí)不會(huì)證(記得陳景潤的一本組合數(shù)學(xué)中有證明,后面要是懂了再來補(bǔ)吧)
對于一個(gè)非失敗態(tài)我們可以通過轉(zhuǎn)換得到一個(gè)失敗態(tài),也就是說(a,b,c)我們可以通過如下的操作得到一個(gè)失敗態(tài),如果a^b < c那么我們從第三堆中取走c-a^b根,如果a^c < b那么我們從第二堆中取走b - a^c根.如果b^c < a那么我們從第一堆中取走a - b^c根。這樣就變成了一個(gè)失敗態(tài)。
由于水平有限,暫時(shí)只能寫這么多了。
這個(gè)題是二維的格雷碼,把兩個(gè)合并起來。
題意是把0到2^(n +m)-1的數(shù)寫成2^n * 2^m的矩陣,使得位置相鄰兩數(shù)的二進(jìn)制表示只有一位之差
這樣的話就是把n位的格雷碼和m位的格雷碼合并起來就行了
拿n = 1 m = 2來說吧
可以自己先窮舉一下會(huì)發(fā)現(xiàn)時(shí)下面的樣子
一
|
二
|
三
|
四
|
000(0) |
100(4) |
110(6) |
010(2) |
001(1) |
101(5) |
111(7) |
011(3) |
可以發(fā)現(xiàn)各列的前兩位是一樣的,也是m位的gray(其實(shí)先把所有列合并起來,然后再在后面加上n的gray就成了這個(gè)了)
這樣的話,實(shí)現(xiàn)起來就比較容易了
代碼如下(第n個(gè)gray碼是n ^ (n >> 1)(其中n從0開始))