序列统计

题目连接:

https://www.acwing.com/problem/content/1314/

Description

给定三个正整数 \(N,L,R\),统计长度在 1 到 N 之间,元素大小都在 L 到 R 之间的单调不降序列的数量。

输出答案对 \(10^6+3\) 取模的结果。

Input

输入第一行包含一个整数 T,表示数据组数。

第二到第 T+1 行每行包含三个整数 N,L,R。

Output

输出包含 T 行,每行有一个数字,表示你所求出的答案对 \(10^6+3\) 取模的结果。

Sample Input

2
1 4 5
2 4 5

Sample Output

2
5

Hint

对于第一组输入,满足条件的两个序列为 {4},{5}。

题解

有两种做法,但都用到了映射的思想。

解法1

设序列长度为k,满足\(0≤a_1≤a_2≤...≤a\)\(k-1\)\(≤a_k≤R-L\),设\(x_1=a_1,a_i=a_i-a\)\(i-1\),由于\(x_i\)\(a_i\)之间的差值,他们只有具有相对大小关系,而不关注的绝对值。\(x_i\)之和小于等于\(R-L\),由于\(x_i\)可以等于0,我们将\(x_i\)都加1,\(x_i\)都大于0。
\(x_i\)之和小于等于\(R-L+k\),用挡板法求解不等方程:n个小球,凑成k部分小于等于n的球数,则在n个空隙插入k个挡板,第i个挡板前代表第i部分的小球数,结果为\(C(n,k)\)

带入得答案是:\(C(R-L+k,k)\)

解法2

我们将a的大于等于映射成b的大于序列:\(b_1=a_1,b_2=a_2+1,...b_k=a_k+k-1\),\(0≤b_1<b_2<...<b_k≤R-L+k-1\),所以相当于从1到R-L+k中选择k个不同的数。答案为:\(C(R-L+k,k)\)
下面就是要求枚举k从1到n,C(R-L+k,k)的和,直接枚举会超时。将\(C(m+1,m)+C(m+2,m)+...+C(m+n,m)\)化简得:\(C(m+n+1,m+1)-C(m+1,m+1)\)

代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int p=1e6+3;
LL qmi(LL a,LL b){
    LL res=1;
    while(b){
        if(b&1) res=res*a%p;
        a=a*a%p;
        b>>=1;
    }
    return res;
}
LL C(LL a,LL b){
    LL down=1,up=1;
    for(int i=a,j=b;j>=1;--j,--i){
        up=up*i%p;
        down=down*j%p;
    }
    return up*qmi(down,p-2)%p;
}
LL Lucas(LL a,LL b){
    if(a<10000&&b<10000) return C(a,b);
    else return C(a%p,b%p)*Lucas(a/p,b/p)%p;
}
int main(){
    int T;
    cin>>T;
    while(T--){
        LL n,l,r;
        cin>>n>>l>>r;
        cout<<(Lucas(n+r-l+1,n)-1+p)%p<<endl;
    }
    return 0;
}
posted @ 2020-04-16 23:05  0x4f  阅读(136)  评论(0编辑  收藏  举报