[BZOJ4403]序列统计
Description:
给定n,l,r,求长度为[1,n]取值范围在[l,r]的LIS数
Hint:
\(n,l,r \le 10^9\)
Solution:
满满的套路......
首先我们考虑转化求这个不降序列
而是给每个数加上它的下标后,去求[l+1,r+n] 的上升序列
显然是 \(\sum_{i=1}^n C_{r-l+i}^{i}\) = \(\sum C_{r-l+i}^{r-l}\)
设r-l+1为m,则答案可以化简:
\(\sum_{i=1}^n C_{m+i-1}^{m-1}\)
=\(\sum_{i=2}^n C_{m+i-1}^{m-1}+C_{n+m}^{m-1}+C_{m}^{m}-1\)
=\(C_{n+m}^{m}\)
lucas即可
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1
#define rs p<<1|1
using namespace std;
typedef long long ll;
const ll mxn=1e6+2,mod=1e6+3;
ll n,m,cnt,hd[mxn];
inline ll read() {
char c=getchar(); ll x=0,f=1;
while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
return x*f;
}
inline void chkmax(ll &x,ll y) {if(x<y) x=y;}
inline void chkmin(ll &x,ll y) {if(x>y) x=y;}
struct ed {
ll to,nxt;
}t[mxn<<1];
inline void add(ll u,ll v) {
t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
}
ll l,r,fac[mxn+50],ifac[mxn+50];
ll qpow(ll a,ll b) {
ll res=1,bs=a;
while(b) {
if(b&1) res=1ll*res*bs%mod;
bs=1ll*bs*bs%mod;
b>>=1;
}
return res;
}
ll C(ll x,ll y) {
if(x<y) return 0;
if(x<mod&&y<mod) return 1ll*fac[x]*ifac[x-y]%mod*ifac[y]%mod;
return 1ll*C(x/mod,y/mod)*C(x%mod,y%mod)%mod;
}
int main()
{
ll T; T=read();
fac[0]=1; ifac[0]=1;
for(ll i=1;i<=mxn;++i) fac[i]=1ll*fac[i-1]*i%mod;
ifac[mxn]=qpow(fac[mxn],mod-2);
for(ll i=mxn-1;i>=1;--i) ifac[i]=1ll*ifac[i+1]*(i+1)%mod;
while(T--) {
n=read(); l=read(); r=read();
printf("%lld\n",(C(n+r-l+1,r-l+1)-1+mod)%mod);
}
return 0;
}