[NBOJ0031][Nim-B* Sum]

[題目要求]

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

 

相關文章
相關標籤/搜索