Bzoj4403: 序列统计

题面

戳我

Sol

考虑枚举长度i
与l,r无太大关系,只需要关心这len=r-l+1个数的放法。。
我们把len个数看成这么多个不同的盒子,i的长度看成相同的i个球
相当于把这i个球放到这些盒子里,可以重复放的方案数
也就是求可重组合,也就是组合数\(C_{len-1}^{len+i-1}\)公式自己学去
就是要求\(\sum_{i=1}^{n}C_{len-1}^{len+i-1}\)补一个\(C_{n}^{n}\)
由公式\(C_{n+1}^{n+r+1}=\sum_{i=0}^{r}C_{n}^{n+r}\)
答案就是\(C_{n}^{n+len}-C_{n}^{n}=C_{n}^{n+len}-1\)
再用lucas定理就好了

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(1e7 + 1), MOD(1e6 + 3);

IL ll Read(){
    char c = '%'; ll x = 0, z = 1;
    for(; c > '9' || c < '0'; c = getchar()) if(c == '-') z = -1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = x * 10 + c - '0';
    return x * z;
}

int fac[MOD] = {1};

IL int Pow(RG ll x, RG ll y){
	RG ll cnt = 1;
	for(; y; y >>= 1, x = x * x % MOD) if(y & 1) cnt = cnt * x % MOD;
	return cnt;
}

IL int C(RG ll n, RG ll m){
	if(n < m) return 0;
	return 1LL * fac[n] * Pow(fac[m], MOD - 2) % MOD * Pow(fac[n - m], MOD - 2) % MOD;
}

IL int Lucas(RG ll n, RG ll m){
	if(n < m) return 0; if(!m) return 1;
	return 1LL * Lucas(n / MOD, m / MOD) * C(n % MOD, m % MOD) % MOD;
}

int main(RG int argc, RG char *argv[]){
	for(RG int i = 1; i < MOD; ++i) fac[i] = 1LL * fac[i - 1] * i % MOD;
	for(RG int T = Read(), n, l, r, len; T; --T){
		n = Read(); l = Read(); r = Read(); len = r - l + 1;
		printf("%d\n", (Lucas(n + len, len) - 1 + MOD) % MOD);
	}
	return 0;
}

posted @ 2018-01-10 20:50  Cyhlnj  阅读(148)  评论(0编辑  收藏  举报