当所有的数字全部变为0时,下一个进行操作的人将无路可走,所以本题的关键在于:

如果k=1,那么比赛永无止境,结果为平局;如果k>1,计算出让所有数字变为0的总共的操作数,根据奇偶性判断,奇数先手胜,偶数后手胜。

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

由于数据组数过多,我们选择预处理数组。对于[1, 1e+5]中每一个可能的整数p,[1, 100]中每一个可能的整数k,进行p/k操作,求使p变为0的操作数(根据题意,每一次从集合中删除p时,将增添k个$\lfloor p/k \rfloor$)。

上述操作本质上为求一个深度为$\lceil \log_k p \rceil$的满k叉树节点数,亦即等比数列求和:$k^{0}+k^{1}+k^{2}+...+k^{n-1}$

我们考虑使用秦九韶算法(霍纳法则),对于等比数列,可以归纳为:先乘以k再加1

代码:

#include <bits/stdc++.h>
using namespace std;

int l, r, k;
int kp[105][100005];
void pre()
{
    for(int k=2;k<=100;++k){
        for(int p=1;p<=100000;++p){
            int temp=p;
            while(temp){
                temp/=k;
                kp[k][p]=kp[k][p]*k+1;//秦九韶算法,On实现一元n次多项式计算
            }
        }
    }
}
int main()
{
    pre();
    while(cin>>l>>r>>k){
        if(k==1) {cout<<"Draw"<<endl;continue;}
        int ans=0;
        for(int i=l;i<=r;++i)
            ans+=kp[k][i];
        if(ans%2) cout<<"XHRlyb"<<endl;
        else cout<<"Cwbc"<<endl;
    }
    return 0;
}

 再插入一个更明显的更亲民的秦九韶算法:

#include <bits/stdc++.h>
using namespace std;

int l, r, k;
int kp[105][100005];
void pre()
{
    for(int k=2;k<=100;++k){
        for(int p=1;p<=100000;++p){
            int temp=p;z=0;
            
            ////秦九韶算法,On实现一元n次多项式计算
            while(temp/k) {z++;temp/=k;}//计算最高次次数
            for(int i=z;i>=0;--i) kp[k][p]=kp[k][p]*k+1;
        }
    }
}
int main()
{
    pre();
    while(cin>>l>>r>>k){
        if(k==1) {cout<<"Draw"<<endl;continue;}
        int ans=0;
        for(int i=l;i<=r;++i)
            ans+=kp[k][i];
        if(ans%2) cout<<"XHRlyb"<<endl;
        else cout<<"Cwbc"<<endl;
    }
    return 0;
}

最后说一下pre()的复杂度问题,最坏情况lg1e5为10数量级,所以数据量大概在1e8左右,刚好过时限

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄