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) 收藏 举报
浙公网安备 33010602011771号