HDU 2516 (Fabonacci Nim) 取石子游戏
這道題的結論就是,石子的個數為斐波那契數列某一項的時候,先手必敗;否則,先手必勝。
結論很簡單,但是證明卻不是特別容易。找了好幾篇博客,發現不一樣的也就兩篇,但是這兩篇給的證明感覺證得不清不楚的,沒看太懂。
首先,證明要依賴一個鄧肯多夫定理(Zeckendorf's Theorem):任何一個正整數一定能分解成若干個不重復且不相鄰的斐波那契數之和。
首推維基百科上的英文證明,很嚴謹也能看懂,證明的過程中還用到了一條引理,但是很容易用數學歸納法證明,所以整個過程都是十分嚴謹的:http://en.wikipedia.org/wiki/Zeckendorf%27s_theorem
然后對于一個必勝狀態,則這個數可以分解成多個斐波那契數之和,或者可以對應地將這堆石子分成若干堆來看,而且每堆石子的數量都是一個斐波那契數。
先手取完最小的那個石子堆,其數量為Fi,由于鄧肯多夫定理定理,第二小的石子堆Fj ≥ Fi+2 = Fi + Fi+1 > 2Fi,所以后手面對的局面就是若干個斐波那契數,而且不能一次取完最小的石子堆。然后等后手取完以后再繼續將剩下的石子數分解,再取最小的斐波那契數即可。
?
對于一個先手必敗狀態,也就是一個斐波那契數局面,證明不太會證。
這有一篇證明,但是感覺不嚴謹啊:http://blog.csdn.net/acm_cxlove/article/details/7835016
里面說
如果先手第一次取的石子數y>=f[k-1]/3,則這小堆所剩的石子數小于2y,即后手可以直接取完
這是對的,但是他為什么沒有討論y < f[k-1]/3的情況嘞?
?
然后又找到一篇證明,http://yjq24.blogbus.com/logs/46150651.html
前面還好,但是最后那個不等式我又是看得不明不白的。不知道i,j分別代表什么的下標,+_+
?
于是還是感慨一下:看論文找證明還是“帆 檣”看英文資料,里面的證明十分簡潔嚴謹。
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 typedef long long LL; 5 6 const LL maxn = (1LL << 31); 7 LL a[50]; 8 9 int main() 10 { 11 a[0] = 1, a[1] = 2; 12 for(int i = 2; a[i-1] <= maxn; i++) 13 a[i] = a[i-1] + a[i-2]; 14 LL n; 15 while(scanf("%lld", &n) == 1 && n) 16 { 17 int i = lower_bound(a, a + 45, n) - a; 18 printf("%s\n", a[i] == n ? "Second win" : "First win"); 19 } 20 21 return 0; 22 } 代碼君?
轉載于:https://www.cnblogs.com/AOQNRMGYXLMV/p/4418186.html
總結
以上是生活随笔為你收集整理的HDU 2516 (Fabonacci Nim) 取石子游戏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [tools]notepad++当前文件
- 下一篇: Objective-C NSSetNS