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 
京公网安备 11010502036488号