该题由于数据比较水,很多不完全的解法也可以通过,经过调查研究,这里写一下较为完整的解法,有遗漏请指正。
记左区间为,右区间为。为的位数。
拼接得到的数为。
由模的性质可得,对于,都有,所以要遍历,最多只需要遍历次。
对于,这里直接对分段进行处理,相同位数分为一段。段数最多为r最大位数。
然后遍历简化的,和分出的段,先计算,其中为在段首的数,为在段尾的数
若,此时对于,就找到了使
若,计算。若,则对于,在该段中找不到使。其中表示要使,至少需要比大多少。反之可以找到。
若遍历完所有段,都找不到,则此时的可以使先手必胜。结束所有遍历。
若某段中找到,则先手不能选,进行遍历下一个。
若遍历完所有,都没有找到使先手必胜,则先手必败。
时间复杂度为,其中为的位数
AC代码如下:
#include <iostream>
using namespace std;
typedef long long ll;
typedef struct Seg{
ll w;
ll lef;
ll rig;
}Seg;
int main(){
int T;
cin>>T;
while(T--){
ll L1,R1,L2,R2,mod;
cin>>L1>>R1>>L2>>R2>>mod;
R1=min(R1,L1+mod-1);//多于mod的部分重复了
//按位数分割
Seg seg[15];ll cnt=0;
for(ll i=1,w=1;i<=10;i++,w*=10){
if((w<=R2)&&(w*10-1>=L2)){//有交集
seg[cnt].w=w;
seg[cnt].lef=max(w,L2);
seg[cnt].rig=min(w*10-1,R2);
++cnt;
}
}
ll i=L1;
for(;i<=R1;i++){
int fg=false;
for(ll j=0;j<cnt;j++){
ll t=i*seg[j].w+seg[j].lef;//使用段的第一个值计算余数
if(t%mod!=0 && seg[j].lef+(mod-t%mod)>seg[j].rig){//余数为0直接找到,不为0通过计算范围判断是否能找到
;//该段中找不到使余数为零
}else{
fg=true;//找到了使余数为零的数,有某一段找到即可break
break;
}
}
if(fg){
//此时不能选i,继续寻找
}else{
break;//找到了i,使对方无法找到使余数为零的数,break
}
}
if(i>R1){//不存在i
cout<<"LOSE"<<endl;
}else{
cout<<"WIN"<<endl;
}
}
return 0;
}