bzoj 4403: 序列统计
Time Limit: 3 Sec Memory Limit: 128 MB
[Submit][Status][Discuss]
Description
给定三个正整数N、L和R,统计长度在1到N之间,元素大小都在L到R之间的单调不降序列的数量。输出答案对10^6+3取模的结果。
Input
输入第一行包含一个整数T,表示数据组数。
第2到第T+1行每行包含三个整数N、L和R,N、L和R的意义如题所述。
1≤N,L,R≤10^9,1≤T≤100,输入数据保证L≤R。
Output
输出包含T行,每行有一个数字,表示你所求出的答案对10^6+3取模的结果。
Sample Input
2
1 4 5
2 4 5
1 4 5
2 4 5
Sample Output
2
5
//【样例说明】满足条件的2个序列为[4]和[5]。
很简单的组合数学题。
首先发现元素大小并没有什么卵用,只需要知道可选数的种类即可。
单调不降就相当于把排列变成组合(组合的含义就是单调不降排列数量)。
设len=r-l+1,那么答案就是C(len,1)+C(len+1,2)+...+C(len+n-1,n)。(有可重复元素的组合)
化简一下,把上式+C(len,0)再-C(len,0),可得:
ANS=C(len+n,n)-1。
发现mod才是10^6级别的,所以把阶乘和逆元处理出来之后再写个卢卡斯就可以了
(而且这个卢卡斯最多只会跑两层)。
5
//【样例说明】满足条件的2个序列为[4]和[5]。
很简单的组合数学题。
首先发现元素大小并没有什么卵用,只需要知道可选数的种类即可。
单调不降就相当于把排列变成组合(组合的含义就是单调不降排列数量)。
设len=r-l+1,那么答案就是C(len,1)+C(len+1,2)+...+C(len+n-1,n)。(有可重复元素的组合)
化简一下,把上式+C(len,0)再-C(len,0),可得:
ANS=C(len+n,n)-1。
发现mod才是10^6级别的,所以把阶乘和逆元处理出来之后再写个卢卡斯就可以了
(而且这个卢卡斯最多只会跑两层)。
#include<bits/stdc++.h> #define ll long long #define ha 1000003 #define maxn 1000005 using namespace std; ll jc[maxn],ni[maxn]; ll T,l,r,n,len; inline ll ksm(ll x,ll y){ ll an=1; for(;y;y>>=1,x=x*x%ha) if(y&1) an=an*x%ha; return an; } inline void init(){ jc[0]=1; for(int i=1;i<ha;i++) jc[i]=jc[i-1]*(ll)i%ha; ni[ha-1]=ksm(jc[ha-1],ha-2); for(int i=ha-2;i>=0;i--) ni[i]=ni[i+1]*(ll)(i+1)%ha; } inline ll C(ll x,ll y){ if(x<y) return 0; return jc[x]*ni[y]%ha*ni[x-y]%ha; } inline ll Lucas(ll x,ll y){ ll ans=1,px,py; while(x||y){ px=x%ha,py=y%ha; x/=ha,y/=ha; ans=ans*C(px,py)%ha; } return ans; } int main(){ init(); scanf("%lld",&T); while(T--){ scanf("%d%d%d",&n,&l,&r); len=r-l+1; printf("%lld ",(Lucas(len+n,n)-1+ha)%ha); } return 0; }