[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;
}

posted @ 2019-03-30 18:17  cloud_9  阅读(98)  评论(0编辑  收藏  举报