题目描述:
给定三个正整数N、L和R,统计长度在1到N之间,元素大小都在L到R之间的单调不降序列的数量。输出答案对10^6+3取模的结果。
题目分析:
序列是有序的,那么我们只关心每种元素有多少个。
把
[
L
,
R
]
[L,R]
[L,R]的每一个数看成一个盒子,元素看成球,那么就相当于把
n
n
n个相同的球放进
R
−
L
+
1
R-L+1
R−L+1个盒子里面,盒子可以为空,球可以不放完。
再加一个盒子,把没放的球放进这个盒子里面,原问题就等价于把
n
n
n个相同的球放进
R
−
L
+
2
R-L+2
R−L+2个盒子里,盒子可以为空的方案,经典隔板法,再减去
n
n
n个球都放到了空盒子的一种方案。
答案即为
C
n
+
R
−
L
+
1
R
−
L
+
1
−
1
C_{n+R-L+1}^{R-L+1}-1
Cn+R−L+1R−L+1−1
或者解决这种不下降问题,可以把第 i i i个元素加 i i i转化成上升序列,选 i i i个数的话权值范围就是 [ L , R + i − 1 ] [L,R+i-1] [L,R+i−1],即 C R − L + i i C_{R-L+i}^i CR−L+ii,答案就是对它求和。
Code:
#include<cstdio>
#define maxn 1000005
const int mod = 1e6+3;
int T,n,L,R,fac[maxn],inv[maxn];
void Pre(const int N){
fac[0]=fac[1]=inv[0]=inv[1]=1;
for(int i=2;i<=N;i++) fac[i]=1ll*fac[i-1]*i%mod,inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
for(int i=2;i<=N;i++) inv[i]=1ll*inv[i]*inv[i-1]%mod;
}
inline int C(int n,int m){return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;}
inline int Lucas(int n,int m){
int ret=1,s,t;
while(n&&m){
if((s=n%mod)<(t=m%mod)) return 0;
ret=1ll*ret*C(s,t)%mod,n/=mod,m/=mod;
}
return ret;
}
int main()
{
Pre(mod-1);
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&L,&R);
printf("%d\n",(Lucas(n+R-L+1,R-L+1)-1+mod)%mod);
}
}