1 分析胜负
仅当时候,会陷入无限循环,两者会平手。
当大于
时候,每个数字
总是会变成
个
向下取整,然后再以此规则变化。两人每次选择哪个数字其实没有影响,就看一共要消除多少次,才能让这里所有的数字都变成0。
显然,这和数字的大小有关系,当在
到
的范围内,每个数字要消除1次。
当在到
的范围内,每个数字要消除
次,因为消除一次之后会变成k个
到
的范围内的数字。
同理,在当在到
的范围内,每个数字要消除
次。
以此类推。
对系统初始状态的每个数字,计算要消除多少次并加起来,总的如果是奇数就是那个先手的人赢了,否则就是另一个人赢了。
2 前缀和计算
其实不用前缀和也是能算的,只是到
之间的所有数字要消除多少次不那么好算,可以写一个计算从
到数字
全部放在一起一共要消除多少次的函数
,这样前面一段的分析就很适合来算这个东西了,然后所求就是看看
是奇数还是偶数。
3 程序
#include<bits/stdc++.h> using namespace std; int l,r,k; #define ll long long ll sum(ll n) { //k^0 ~ k^1-1 可1次消除 //k^1 ~ k^2-1 可1+k次消除 //k^2 ~ k^3-1 可1+k+k^2次消除 ll kf = 1;//初始,k的0次方为1 ll ret = 0;//总消除次数 ll p = 1;//当前这些数字所需消除次数 while(kf*k-1<n) { ret += p*(kf*k-1 - kf + 1)%2;//反正最后是求差的奇偶,这里模2不影响 p += k; kf = kf*k; } //最后剩下的那些 ret += p*(n - kf + 1); return ret; } int main() { while(scanf("%d%d%d",&l,&r,&k)!=EOF) { //仅当k=1时会无限循环导致平手 if(k==1) puts("Draw"); else if(((sum(r)-sum(l-1))&1)==1)//奇数 puts("XHRlyb"); else puts("Cwbc"); } return 0; } //GitHub求star啦:https://github.com/LauZyHou/Algorithm-To-Practice