该题由于数据比较水,很多不完全的解法也可以通过,经过调查研究,这里写一下较为完整的解法,有遗漏请指正。


记左区间为LL,右区间为RRw(r)=10i,rR,iw(r)=10^{i},r\in R,irr的位数。

拼接得到的数为n=(lw(r)+r),lL,rRn=(l*w(r)+r),l\in L,r\in R

由模的性质可得,对于rR\forall r\in R,都有(lw(r)+r)%mod=((l+mod)w(r)+r)%mod,lL(l*w(r)+r)\%mod=((l+mod)*w(r)+r)\%mod,l\in L,所以要遍历LL,最多只需要遍历modmod次。

对于w(r)w(r),这里直接对RR分段进行处理,相同位数分为一段。段数最多为r最大位数。

然后遍历简化的LL,和分出的段,先计算t=(lw(rf)+rf)%modt=(l*w(r_f)+r_f)\%mod,其中rfr_f为在段首的数,rer_e为在段尾的数

t=0t=0,此时对于ll,就找到了r=rfr=r_f使n%mod=0n\%mod=0

t0t\neq0,计算need=modtneed=mod-t。若rf+need>rer_f+need>r_e,则对于ll,在该段中找不到rr使n%mod=0n\%mod=0。其中needneed表示要使n%mod=0n\%mod=0rr至少需要比rfr_f大多少。反之可以找到r=rf+needr=r_f+need

若遍历完所有段,都找不到rr,则此时的ll可以使先手必胜。结束所有遍历。

若某段中找到rr,则先手不能选ll,进行遍历下一个ll

若遍历完所有ll,都没有找到ll使先手必胜,则先手必败。


时间复杂度为mod(iR2iL2+1)mod*(i_{R_2}-i_{L_2}+1),其中iL2,iR2i_{L_2},i_{R_2}L2,R2L_2,R_2的位数


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;
}