1. 程式人生 > >bzoj 4403: 序列統計

bzoj 4403: 序列統計

its mes 數量 stdin cpp 統計 namespace log line

Description

給定三個正整數N、L和R,統計長度在1到N之間,元素大小都在L到R之間的單調不降序列的數量。輸出答案對10^6+3取模的結果。

Solution

將所有元素\(a[i]\)加上\(i\)之後,就變成求單調上升序列了,那麽\(a[i]\)的取值範圍就是\([L+1,R+n]\),且只有 \(R-L+n\) 種選擇了
如果要求的序列長度為 \(n\),那麽答案就是 \(C_{R-L+n}^{n}\)
本題要求的是 \(\sum_{i=1}^{n}C_{R-L+i}^{R-L}\)
\(R-L=j\)
要求的就是 \(C_{j+1}^{j}+C_{j+2}^{j}....+C_{j+n}^{j}\)


加入一項 \(C_{j+1}^{j+1}\)
原式變為 \(C_{j+1}^{j+1}-1+C_{j+1}^{j}+C_{j+2}^{j}....+C_{j+n}^{j}\)
由組合數遞推式:\(C_{n}^{m}=C_{n-1}^{m-1}+C_{n-1}^{m}\) 逐項合並
就可以得到最後的答案:\(C_{n+R-L+1}^{R-L+1}\)
觀察到模數較小且為質數,直接Lucas求即可.

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10,mod=1e6+3;
int Fac[N];
int qm(int
x,int k){ int sum=1; while(k){ if(k&1)sum=1ll*sum*x%mod; x=1ll*x*x%mod;k>>=1; } return sum; } inline int C(int n,int m){ if(n<m)return 0; return 1ll*Fac[n]*qm(Fac[m],mod-2)%mod*qm(Fac[n-m],mod-2)%mod; } inline int Lucas(int n,int m){ if(m==0)return 1; return 1ll*Lucas(n/mod,m/mod)*C(n%mod,m%mod)%mod; } int
main(){ freopen("pp.in","r",stdin); freopen("pp.out","w",stdout); int n,L,R,T;cin>>T; Fac[0]=1;for(int i=1;i<N;i++)Fac[i]=1ll*Fac[i-1]*i%mod; while(T--){ scanf("%d%d%d",&n,&L,&R); printf("%d\n",(Lucas(n+R-L+1,R-L+1)-1+mod)%mod); } return 0; }

bzoj 4403: 序列統計