组合的知识大大欠缺啊。。好好学习一下。
先膜出题人
yts1999
大爷。
首先转化一下问题:
求长度在
1
到
那么这个问题就相当于在区间
[L+1,R+N]
这
R−L+N
个数中选择
N
个的方案数,即
为了表述方便,我们令
M=R−L+1
,上式转化为
CM−1M+N−1
。
所以答案为
∑i=1NCM−1i+M−1
因为
CMN=CMN−1+CM−1N−1
所以我们有以下等价转化:
∑Ni=1CM−1i+M−1
=(∑Ni=1CM−1i+M−1)+CMM−1
=(∑Ni=2CM−1i+M−1)+CMM+1−1
=(∑Ni=3CM−1i+M−1)+CMM+2−1
...
=CMN+M−1
然后用 Lucas 定理解决。
#include<iostream>
#include<cstdio>
#define ll long long
#define M 1000003
using namespace std;
ll fac[M],inv[M];
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
inline void pre()
{
fac[0]=inv[1]=inv[0]=1;
for (int i=1;i<M;i++)
fac[i]=fac[i-1]*i%M;
for (int i=2;i<M;i++)
inv[i]=(M-M/i)*inv[M%i]%M;
for (int i=1;i<M;i++)
inv[i]=inv[i]*inv[i-1]%M;
}
ll C(int n,int m)
{
if (n<m) return 0;
if (n<M&&m<M)
return fac[n]*inv[m]%M*inv[n-m]%M;
return C(n/M,m/M)*C(n%M,m%M)%M;
}
int main()
{
int T=read();
pre();
while (T--)
{
int n=read(),l=read(),r=read(),m=r-l+1;
printf("%d\n",(C(n+m,m)+M-1)%M);
}
return 0;
}