题目描述
传送门
题目大意:给定三个正整数N、L和R,统计长度在1到N之间,元素大小都在L到R之间的单调不降序列的数量。输出答案对10^6+3取模的结果。
题解
设m=r-l+1,那么我们相当于m个数,每个数选择xi个,使最后的总和为N
x1+x2+…+xm=N 这其实就相当于N个球放到M个盒子中,允许出现空盒子的方案数。
利用插板法不难得到答案就是C(N+m-1,m-1)
那么这道题的答案就是
ans=∑Ni=1C(i+m−1,m−1)
设
t=m−1
,那么
ans=C(t+1,t)+C(t+2,t)+...+C(t+n,t)
我们强行加入
C(t+1,t+1)
,将式子进行化简。发现
C(t+1,t)+C(t+1,t+1)=C(t+2,t+1)
,然后就可以一项一项的向后合并,最后得到
C(t+n+1,t+1)
那么答案就是
C(t+n+1,t+1)−C(t+1,t+1)=C(t+n+1,t+1)−1
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define LL long long
#define p 1000003
#define N 2000000
using namespace std;
int jc[N],inv[N];
int T,n,l,r,m;
int quickpow(LL num,int x)
{
LL base=num%p; LL ans=1;
while (x){
if (x&1) ans=ans*base%p;
x>>=1;
base=base*base%p;
}
return (int)ans;
}
LL C(LL n,LL m)
{
if (m>n) return 0;
return (LL)jc[n]*quickpow(jc[m],p-2)%p*quickpow(jc[n-m],p-2)%p;
}
LL calc(LL n,LL m)
{
if (m==0) return 1;
return calc(n/p,m/p)*C(n%p,m%p)%p;
}
int main()
{
freopen("a.in","r",stdin);
scanf("%d",&T);
jc[0]=1;
for (int i=1;i<=p;i++) jc[i]=(LL)jc[i-1]*i%p;
//for (int i=0;i<=p;i++) inv[i]=quickpow(jc[i],p-2);
while (T--) {
scanf("%d%d%d",&n,&l,&r);
m=(r-l+1)-1;
//cout<<m+n+1<<" "<<m+1<<endl;
LL ans=calc(m+n+1,m+1)-1;
ans=(ans%p+p)%p;
printf("%lld\n",ans);
}
}