题意简述
noi.ac再次蒯题,实锤了…
请你求长度在 [ 1 , n ] [1,n] [1,n] 范围内,值域在 [ l , r ] [l,r] [l,r] 范围内的序列中,不下降序列有多少个。答案对 1000003 1000003 1000003(是质数)取膜。
多组数据,数组组数 T ≤ 100 T\le 100 T≤100 ,每组数据 n , l , r ≤ 1 e 9 n,l,r\le 1e9 n,l,r≤1e9 ,并且保证 l ≤ r l\le r l≤r
思路框架
首先,在
[
l
,
r
]
[l,r]
[l,r] 范围内,和在
[
1
,
r
−
l
+
1
]
[1,r-l+1]
[1,r−l+1] 范围内,没有本质上的区别。
设
m
=
r
−
l
+
1
m=r-l+1
m=r−l+1,然后答案就是
C
n
+
m
m
−
1
C_{n+m}^{m}-1
Cn+mm−1
具体思路
我们先求长度固定为 k k k 的时候,有多少满足条件的序列,然后取遍 k = 1 , 2 ⋯ n k=1,2\cdots n k=1,2⋯n ,求和。
求有多少固定长度非严格上升子序列
严格上升怎么做
长度为 k k k 的时候,值域在 [ 1 , m ] [1,m] [1,m] 内的严格上升序列的格式就是 C m k C_{m}^{k} Cmk 。因为我们只要在 [ 1 , m ] [1,m] [1,m] 内选出来 k k k 个数,然后把它排一下序,那就能得到一个长度为 k k k ,值域在 [ 1 , m ] [1,m] [1,m] 内的一个严格上升序列了。
如何转化成非严格上升
我们在选严格上升序列的时候,假设我们当前选到的数为 x x x,那么下一个位置珂以是 x + 1 , x + 2... m x+1,x+2...m x+1,x+2...m,有 m − x m-x m−x 种选择。而选非严格上升序列的时候,却有 $m-x+1 $种选择。
那这个时候,我们只要把 m m m 变成 m + 1 m+1 m+1 ,那答案就和严格上升的时候一样了!!
序列的长度为 k k k ,那么我们在选第 [ 1 , k − 1 ] [1,k-1] [1,k−1]这些位置的时候,都要把 m m m 变成 m + 1 m+1 m+1。那一共就是变成 m + k − 1 m+k-1 m+k−1。
总结一下,长度为 k k k 值域在 [ 1 , m ] [1,m] [1,m] 之间的非严格上升序列个数为 C m + k − 1 k C_{m+k-1}^{k} Cm+k−1k
优化求和
我们要求 ∑ i = 1 n C m + i − 1 i = C m 1 + C m + 1 2 + C m + 2 3 . . . + C m + n − 1 n \sum\limits_{i=1}^{n} C_{m+i-1}^{i}=C_{m}^1+C_{m+1}^2+C_{m+2}^3...+C_{m+n-1}^{n} i=1∑nCm+i−1i=Cm1+Cm+12+Cm+23...+Cm+n−1n
显然, C n m = C n − 1 m + C n − 1 m − 1 C_{n}^{m}=C_{n-1}^{m}+C_{n-1}^{m-1} Cnm=Cn−1m+Cn−1m−1
那也就是说,我们珂以用两个相邻的 C n x x x C_{n}^{xxx} Cnxxx 得到一个 C n + 1 x x x C_{n+1}^{xxx} Cn+1xxx。
那么我们考虑给第一项加上一个 C m 0 C_{m}^{0} Cm0,也就是 1 1 1,然后最后减掉一个 C m 0 C_{m}^{0} Cm0。
那我们开始推式子了,系好安全带(为了方便理解,我拆开
Σ
\Sigma
Σ):
原式
=
C
m
0
+
C
m
1
+
C
m
+
1
2
+
C
m
+
2
3
.
.
.
+
C
m
+
n
−
1
n
−
1
=C_{m}^{0}+C_{m}^{1}+C_{m+1}^{2}+C_{m+2}^3...+C_{m+n-1}^n-1
=Cm0+Cm1+Cm+12+Cm+23...+Cm+n−1n−1
=
C
m
+
1
1
+
C
m
+
1
2
+
C
m
+
2
3
+
.
.
.
+
C
m
+
n
−
1
n
−
1
=C_{m+1}^{1}+C_{m+1}^{2}+C_{m+2}^3+...+C_{m+n-1}^n-1
=Cm+11+Cm+12+Cm+23+...+Cm+n−1n−1
=
C
m
+
2
2
+
C
m
+
2
3
+
.
.
.
.
+
C
m
+
n
−
1
n
−
1
=C_{m+2}^{2}+C_{m+2}^{3}+....+C_{m+n-1}^n-1
=Cm+22+Cm+23+....+Cm+n−1n−1
=
C
m
+
n
−
1
n
−
1
+
C
m
+
n
−
1
n
−
1
=C_{m+n-1}^{n-1}+C_{m+n-1}^{n}-1
=Cm+n−1n−1+Cm+n−1n−1
=
C
m
+
n
n
−
1
=C_{m+n}^{n}-1
=Cm+nn−1
所以答案就是 C m + n n − 1 C_{m+n}^{n}-1 Cm+nn−1。预处理阶乘(逆元)+Lucas定理。
代码
#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
#define mod 1000003
#define N (mod<<1)
#define int long long
#define F(i,l,r) for(int i=l;i<=r;++i)
#define D(i,r,l) for(int i=r;i>=l;--i)
#define Fs(i,l,r,c) for(int i=l;i<=r;c)
#define Ds(i,r,l,c) for(int i=r;i>=l;c)
#define MEM(x,a) memset(x,a,sizeof(x))
#define FK(x) MEM(x,0)
#define Tra(i,u) for(int i=G.Start(u),__v=G.To(i);~i;i=G.Next(i),__v=G.To(i))
#define p_b push_back
#define sz(a) ((int)a.size())
#define iter(a,p) (a.begin()+p)
void R1(int &x)
{
x=0;char c=getchar();int f=1;
while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=(f==1)?x:-x;
}
void Rd(int cnt,...)
{
va_list args;
va_start(args,cnt);
F(i,1,cnt)
{
int* x=va_arg(args,int*);R1(*x);
}
va_end(args);
}
int fac[N],ifac[N];
//阶乘,和阶乘的逆元
void Init()
{
fac[0]=1;
F(i,1,mod-1) fac[i]=fac[i-1]*i%mod;
ifac[mod-1]=mod-1;
//mod是质数,那么(mod-1)! %mod=mod-1,这个是Wilson定理
//然后mod-1的逆元,显然是mod-1
D(i,mod-2,0) ifac[i]=ifac[i+1]*(i+1)%mod;
}
int n,l,r;
void Input()
{
Rd(3,&n,&l,&r);
}
int C(int n,int m) //Lucas定理
{
if (m>n) return 0;
if (n<mod and m<mod)
{
return fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}
return C(n/mod,m/mod)*C(n%mod,m%mod)%mod;
}
void Soviet()
{
int len=r-l+1; //len就是m了
printf("%lld\n",(C(n+len,len)+mod-1)%mod);
}
#define Flan void
Flan IsMyWife()
{
Init();
int t;R1(t);
F(i,1,t)
{
Input();
Soviet();
}
}
#undef int //long long
}
int main()
{
Flandre_Scarlet::IsMyWife();
getchar();getchar();
return 0;
}