[题目涉及的相关理论与算法]
1,博弈论中的NIM游戏。虽然题目中求的Nim和是Nim游戏中的策略,但是和游戏本身关系不大,相当于实现游戏中一个算法。开始不理解的时候觉得很深奥,但是看过一些介绍之后有了初步的了解就好多了。 推荐一个介绍:,这里面比较详细了介绍了Nim游戏。 2,进制转换的相关运算,这个应该属于基本功。 3,理解“异或运算”实质是在二进制下的不进位加法。本题中出现的运算针对的是B进制下。[题目中需要注意的地方]
觉得有两点值得一说吧,一个是两个B进制下的数进行运算时要注意对准位。数组存的是逆序的结果。就是a[0]存的是最低位的。 还有一个是,额。。在最后算回十进制数时,我的算法是在循环内多乘了一个B,结果要除以B,但是就是这一个多乘,造成提交时的结果溢出了。。到最后慢慢比较后才发现。。所以千万留神,将结果改成用long long型就AC了。最好的解决办法就是改一下循环体的构造,不多乘那一下。。。这也说明系统测试时的数据真的很大。。都是边缘啊= =。[思路过程]
开始没太看明白,后来看过介绍之后,对这个博弈论中的经典问题有了了解。知道了Nim和的定义和求法。后面就比较好办了。顺序就是先将两个数转换为相应的进制,然后按位进行不进位加法。得到的结果再转换为十进制输出。[代码]
#includeusing 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< <<" "< < >t; while((t--) > 0) { casesolve(); } //fclose(stdin); //fclose(stdout); return 0;}
[尾声]
做这道题的时候顺便了解了一点点博弈论中的知识,觉得奥妙无穷啊。今天总算遇到的都是不太讨厌的题目! 还不错~