DestinHistoire

 

BZOJ-4403 序列统计(思维+计数+Lucas定理)

题目描述

  给定三个正整数 \(n,l,r\),统计长度在 \(1\)\(n\) 之间,元素大小都在 \(l\)\(r\) 之间的单调不降序列的数量。输出答案对 \(10^6+3\) 取模的结果。

  数据范围:\(1\leq n,l,r\leq 10^9,1\leq T\leq 100\)

分析

  给序列每个位置 \(i\in [1,n]\) 的数字加上其下标 \(i\),这样问题就转化成统计严格单调递增的序列的数量,同时每个数字可选的值域也变成 \([l+1,r+i]\)。从 \(r-l+i\) 个可选数字中随意选择 \(i\) 个数字,一定是长为 \(n\) 的单调递增序列,方案数为 \(\dbinom{r-l+i}{i}\)

  \(i\)\(1\) ~ \(n\),把答案累加起来,即为:

\[\begin{aligned}&\sum_{i=1}^{n}\dbinom{r-l+i}{i}\\ =&\dbinom{r-l+1}{1}+\dbinom{r-l+2}{2}+\cdots+\dbinom{r-l+n}{n}\\ =&\dbinom{r-l+1}{r-l+1}+\dbinom{r-l+1}{r-l}+\dbinom{r-l+2}{r-l}+\cdots+\dbinom{r-l+n}{r-l}-1\\ =&\dbinom{r-l+2}{r-l+1}+\dbinom{r-l+2}{r-l}+\cdots+\dbinom{r-l+n}{r-l}-1\\ =&\dbinom{r-l+n+1}{r-l+1}-1 \end{aligned} \]

代码

#include <bits/stdc++.h>
using namespace std;
long long fac[1000010],p=1e6+3;
long long quick_pow(long long a,long long b)
{
    long long ans=1;
    while(b)
    {
        if(b&1)
            ans=ans*a%p;
        a=a*a%p;
        b=b>>1;
    }
    return ans;
}
long long C(long long n,long long m)
{
    if(m>n)
        return 0;
    return fac[n]*quick_pow(fac[m],p-2)%p*quick_pow(fac[n-m],p-2)%p;
}
long long lucas(long long n,long long m)
{
    if(m==0)
        return 1;
    return C(n%p,m%p)*lucas(n/p,m/p)%p;
}
void init()
{
    fac[0]=1;
    for(int i=1;i<=p;i++)
        fac[i]=(fac[i-1]*i)%p;
}
int main()
{
    init();
    int T;
    cin>>T;
    while(T--)
    {
        int n,l,r;
        cin>>n>>l>>r;
        cout<<(lucas(r-l+n+1,r-l+1)-1+p)%p<<endl;
    }
    return 0;
}

posted on 2020-11-13 16:06  DestinHistoire  阅读(138)  评论(0)    收藏  举报

导航