题目分析:
显然对于题目中所表示的范围:L~R只表示元素所能够取得的区间大小/长度,所以我们可以忽略区间元素本身的大小,只考虑元素可以去到多少个值。于是,我们就可以将题目中的:L~R 区间YY成一个压缩后的区间:1~(R-L+1),注意:这个区间的压缩是不影响最后结果的(当N固定,L=3,R=6与L=1,R=4意义是一样的)。这个时候就可以显然看出这个序列的每个元素的都有(R-L+1)种取值。这个时候我们来转换一下问题,先令M=R-L+1,即每个元素都有M种取值范围,那么原问题就相当于转换成了“N个球放入M个盒子里,盒子可以为空,球也可以不选”的问题了,对于这个问题那么就显然组合数为C(M+N,M),但是不能存在N个球一个都不选的选法,但是这种选法又包含在了转换问题里面,所以最后的答案要-1。即最后的答案为:C(M+N,M)-1。
补充:为什么上面两个问题可以互相转换。对于“N个球放入M个盒子里,盒子可以为空,球也可以不选”的问题,因为盒子可以为空,求也可以不选,所以我们不妨把它假想为有两个盒子,一个盒子有N个球,一个盒子有M个球,两个盒子最后一共取出M个球,所以这个问题的答案就是C(M +N ,M)了。那么再来考虑原问题:“N个元素每个元素有M中取值,允许存在元素不取值,允许不是每个取值都要取到”的问题,就与前面的盒子问题相对应了,不过此处不能存在N个元素都不取值的情况,所以最后答案在C(N+M,M)的基础上-1即可。不知道大家会不会存在这样一个疑惑,就是题目中提到的单调不降如何处理?这样想:有1个球放在1号盒子与2号盒子里都是一样的,只属于一种方案,那么两个数4,5组合在一起有两种可能45和54,但是要因为单调不降,所以最后的方案也只有一个45。
参考代码(此处为旧代码,尚未更新,好像加强了数据):
#include <cstdio>
#define LL long long
const LL Mod=1e6+3;
const LL Inf=1e18;
inline LL Read(){
LL X=0;char CH=getchar();bool F=0;
while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
return F?-X:X;
}
inline void Write(LL X){
if(X<0)X=-X,putchar('-');
if(X>9)Write(X/10);
putchar(X%10+48);
}
LL KSC(LL A,LL B,LL P){
A%=P,B%=P;
LL C=(long double)A*B/P;
LL Ans=A*B-C*P;
if(Ans<0){
Ans+=P;
} else if(Ans>=P) {
Ans-=P;
}return Ans;
}
LL KSM(LL A,LL B,LL C){
int Ans=1%C;
for(;B;B>>=1){
if(B&1){
Ans=KSC(Ans,A,C);
}A=KSC(A,A,C);
}return Ans;
}
LL C(LL A,LL B)
{
if(A<B) return 0;
if(A==B) return 1;
B=B>A-B?A-B:B;
LL GA=1ll,GB=1ll;
for(LL I=0;I<B;I++)
{
GA=(GA*(A-I))%Mod;
GB=(GB*(B-I))%Mod;
}
return (GA*KSM(GB,Mod-2,Mod))%Mod;
}
LL Lucas(LL N,LL M)
{
if(M==0) return 1;
return C(N%Mod,M%Mod)*Lucas(N/Mod,M/Mod)%Mod;
}
int main()
{
LL T=Read(),N,L,R;
while(T--)
{
N=Read();
L=Read();
R=Read();
LL M=R-L+1;
Write(((Lucas(M+N,M)-1)%Mod+Mod)%Mod);
putchar('\n');
}
return 0;
}