题面
题解
给定三个正整数N、L和R,统计长度在1到N之间,元素大小都在L到R之间的单调不降序列的数量。
先从简单的入手:长度为N的答案是多少?单调不降的条件什么用?
单调不降就是不考虑顺序,就是组合。于是就是选值在[L,R]的数,选N个。也就是选N个值在[1,R-L+1]的数。
令M=R-L+1,将N个数看成球,有M个盒子,每个盒子代表一个值,盒子可为空的放法就是答案。排成一排,权值单调不降,用插空法答案就是 CM−1N+M−1 。
原题变成求 ∑Ni=1CM−1i+M−1%p
杨辉三角有个性质:像个拐杖一样的玩意儿:
CMN+M=∑i=0NCM−1i+M−1
证明就是不断拆项留项到出现0为止。
于是这道填空题的答案为: CMN+M−1 ,直接用Lucas定理即可。
于是就又水了一篇博客
代码
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#define maxn 1000100
using namespace std;
int n, L, R, m, p = 1000003, T;
int fac[maxn], inv[maxn];
int Pow(int x, int y){
int res = 1;
while(y){
if(y & 1) res = 1LL * res * x % p;
x = 1LL * x * x % p;
y >>= 1;
}
return res;
}
void Init(){
fac[0] = 1;
for(int i = 1; i < p; i++)
fac[i] = 1LL * fac[i-1] * i % p;
inv[p-1] = Pow(fac[p-1], p-2);
for(int i = p-2; i >= 0; i--)
inv[i] = 1LL * inv[i+1] * (i+1) % p;
}
int C(int n, int m){
if(m > n) return 0;
return 1LL * fac[n] * inv[m] % p * inv[n-m] % p;
}
int Lucas(int n, int m){
if(m > n) return 0;
int ans = 1;
for(; m; n/=p, m/=p)
ans = 1LL * ans * C(n%p, m%p) % p;
return ans;
}
int main(){
scanf("%d", &T);
Init();
while(T --){
scanf("%d%d%d", &n, &L, &R);
m = R - L + 1;
printf("%d\n", (p+Lucas(n+m, m)-1) % p);
}
return 0;
}
最坏的生活,是没有选择的生活。