题面
分析
我们首先考虑长度为 l l ,元素大小在 到 R R 的==单调不降序列==的个数。设元素大小为 到 R R 的元素的个数分别为 则题目转化为求方程 ∑R−L+1i=1xi=l ∑ i = 1 R − L + 1 x i = l 的非负整数解的个数。
设 yi=xi+1 y i = x i + 1 ,则转化为求方程 ∑R−L+1i=1yi=l+R−L+1 ∑ i = 1 R − L + 1 y i = l + R − L + 1 的正整数解得个数。
设
len=R−L+1
l
e
n
=
R
−
L
+
1
,隔板法,得到答案:
题目要求的是长度为 1 1 到 ,元素大小在 L L 到 的单调不降序列的个数。设答案为 Ans A n s ,则
等号两边同时加上 (lenlen) ( l e n l e n ) ,得到
化简, 得
到现在为止思路已经讲完了。然而 1≤N,L,R≤109 1 ≤ N , L , R ≤ 10 9 ,阶乘直接上天。
Lucas定理
对于非负整数m和n和素数p, 同余式:
(mn)≡∏i=0k(mini)(modp), ( m n ) ≡ ∏ i = 0 k ( m i n i ) ( mod p ) ,
成立,其中:
m=mkpk+mk−1pk−1+⋯+m1p+m0, m = m k p k + m k − 1 p k − 1 + ⋯ + m 1 p + m 0 ,
并且
n=nkpk+nk−1pk−1+⋯+n1p+n0 n = n k p k + n k − 1 p k − 1 + ⋯ + n 1 p + n 0
是m和n的p进制展开。 当 m<n m < n 时,二项式系数 (mn)=0 ( m n ) = 0 。
由于结果要对 106+3 10 6 + 3 取模,我们只需要将 N+len N + l e n 和 len l e n 转化为 106+3 10 6 + 3 进制,再将他们对应的每一位用一遍组合公式。因此我们需要预处理出 0 0 到 的阶乘和它们在模 106+2 10 6 + 2 意义下的逆。阶乘可以从0递推得到,然后使用费马小定理,用快速幂计算出 106+2 10 6 + 2 的逆,然后反着推回去。
代码实现
#include <cstdio>
typedef long long ll;
const int ha=1000003;
int ksm(int x, int a) {
int ret=1;
for(; a; ret=(a%2)?(ll)ret*x%ha:ret, x=(ll)x*x%ha, a/=2);
return ret;
}
int jc[ha], ni[ha];
void init() {
jc[0]=1;
for(int i=1; i<ha; i++) jc[i]=(ll)jc[i-1]*i%ha;
ni[ha-1] = ksm(jc[ha-1], ha-2);
for(int i=ha-1; i; i--) ni[i-1]=(ll)ni[i]*i%ha;
}
int c(int n, int m) {
if(n<m) return 0;
return (ll)jc[n]*ni[m]%ha*ni[n-m]%ha;
}
int C(int n, int m) {
int ret=1;
for(; n&&ret; ret=(ll)ret*c(n%ha,m%ha)%ha, n/=ha, m/=ha);
return ret;
}
int T, n, L, R;
int main() {
scanf("%d", &T);
init();
while(T--) {
scanf("%d%d%d", &n, &L, &R);
int len=R-L+1;
printf("%d\n", (C(n+len, len)-1+ha)%ha);
}
return 0;
}