这个公式推的好巧妙啊,我的公式恐惧症又犯了……
借鉴了别的大佬的博客,发现这种求单调不降序列的数量的题目可以把数列里的每一位都加上对应的
i
,这样就把问题转化成了在
对于这题来说,经过上面的转化,问题转化为求 ∑ni=1Cr−lr−l+i 。
根据组合数的性质,我们知道 Cnm=Cn−1m−1+Cn−1m 。
那么我们定义
m=r−l+1
,(表演开始):
∑i=1nCm−1m+i−1=∑i=1nCm−1m+i−1+Cmm−1
把 i=1 提出来
=∑i=2nCm−1m+i−1+Cm−1m+Cmm−1=∑i=2nCm−1m+i−1+Cmm+1−1
以此类推,从前往后把每一项都提出来,最终答案等于 Cmm+n−1 。
这样就可以直接用Lucas定理搞了。
附上AC代码:
#include <cstdio>
using namespace std;
typedef long long ll;
const int mod=1e6+3;
ll t,n,l,r,jc[mod+1],inv[mod+1];
inline ll lucas(int a,int b){
if (a>b) return 0;
if (b<mod) return jc[b]*inv[a]%mod*inv[b-a]%mod;
return lucas(a/mod,b/mod)*lucas(a%mod,b%mod)%mod;
}
int main(void){
jc[0]=inv[0]=jc[1]=inv[1]=1;
for (int i=2; i<mod; ++i) jc[i]=jc[i-1]*i%mod,inv[i]=(mod-mod/i)*inv[mod%i]%mod;
for (int i=2; i<mod; ++i) inv[i]=inv[i]*inv[i-1]%mod;
for (scanf("%lld",&t); t; --t){
scanf("%lld%lld%lld",&n,&l,&r);
printf("%lld\n",(lucas(r-l+1,r-l+1+n)-1+mod)%mod);
}
return 0;
}