http://acm.bupt.edu.cn/onlinejudge/newoj/showProblem/show_problem.php?problem_id=31php
[題目涉及的相關理論與算法]
1,博弈論中的NIM遊戲。雖然題目中求的Nim和是Nim遊戲中的策略,可是和遊戲自己關係不大,至關於實現遊戲中一個算法。開始不理解的時候以爲很深奧,可是看過一些介紹以後有了初步的瞭解就好多了。
推薦一個介紹:http://blog.csdn.net/qiankun1993/article/details/6765688,這裏面比較詳細了介紹了Nim遊戲。
2,進制轉換的相關運算,這個應該屬於基本功。
3,理解「異或運算」實質是在二進制下的不進位加法。本題中出現的運算針對的是B進制下。ios
[題目中須要注意的地方]
以爲有兩點值得一說吧,一個是兩個B進制下的數進行運算時要注意對準位。數組存的是逆序的結果。就是a[0]存的是最低位的。
還有一個是,額。。在最後算回十進制數時,個人算法是在循環內多乘了一個B,結果要除以B,可是就是這一個多乘,形成提交時的結果溢出了。。到最後慢慢比較後才發現。。因此千萬留神,將結果改爲用long long型就AC了。最好的解決辦法就是改一下循環體的構造,很少乘那一下。。。這也說明系統測試時的數據真的很大。。都是邊緣啊= =。算法
[思路過程]
開始沒太看明白,後來看過介紹以後,對這個博弈論中的經典問題有了瞭解。知道了Nim和的定義和求法。後面就比較好辦了。順序就是先將兩個數轉換爲相應的進制,而後按位進行不進位加法。獲得的結果再轉換爲十進制輸出。數組
[代碼]測試
#include<iostream> using namespace std; int const L = 21; //由於位數最多的狀況就是2進制,而2000000對應的2進制不超過21位。因此設L爲21. void casesolve() { int result[L]; int X[L]; int Y[L]; int n,b,x,y; memset(X,0,sizeof(X)); memset(Y,0,sizeof(Y)); memset(result,0,sizeof(result)); cin>>n>>b>>x>>y; int i=0; //輔助的參數。 int max=0; //使用max來記錄兩個轉換後的進制數最高的位數,固然這裏說的「位數」是B進制下的分組數。 while(x != 0) //將x轉換爲b進制。 { X[i++] = x % b; x = x/b; } max = i; //此時max記錄下x的最高位。 i=0; while(y != 0) //同理處理y { Y[i++] = y % b; y = y/b ; } if(i > max) max =i;//比較x和y哪個位數高。 i=0; while(i != max) //這一步是將兩個B進制下進行不進位加法。用到了max。 { result[i] = (X[i] + Y[i]) % b; i++; } int sum = 0; i=max; while((i--) >= 1 ) { sum = sum * b; //注意這兩步驟的順序。這裏是對進制轉換的基本算法。 sum = sum+result[i]; } cout<<n<<" "<<sum<<endl; } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); int t; cin>>t; while((t--) > 0) { casesolve(); } //fclose(stdin); //fclose(stdout); return 0; }
[尾聲]
作這道題的時候順便了解了一點點博弈論中的知識,以爲奧妙無窮啊。今天總算遇到的都是不太討厭的題目! 還不錯~spa