序列统计 解题过程

· · 个人记录

link

发现确定每种元素数量过后序列就唯一了,接下来是统计方案数。 枚举长度 $len$,发现方案数是简单的组合数学,插板法即可,答案为: $$ \dbinom{len + R - L + 1 - 1}{R - L + 1 - 1} = \dbinom{len + R - L}{R - L} $$ 但是 $N$ 太大了,枚举不了欸。 $$ \dbinom{len + R - L}{R - L} = \dfrac{(len + R - L)!}{(R - L)! \times len!} $$ $$ \begin{aligned} &\sum\limits_{len = 1}^{n}\dfrac{(len + R - L)!}{(R - L)! \times len!}\\ =&\dfrac{\sum\limits_{len = 1}^{n}\dfrac{(len + R - L)!}{len!}}{(R - L)!}\\ =&\dfrac{\sum\limits_{len = 1}^{n}\left(\prod\limits_{j = len + 1}^{len + R - L}j\right)}{(R - L)!}\\ \end{aligned} $$ 在模 $10^{6} + 3$ 的意义下最后乘上 $(R - L)!$ 的逆元即可。 。。。 啊不对不对。 不是这样,重推。令 $X = R - L$。 $$ \begin{aligned} &\sum\limits_{len = 1}^{n}\dbinom{n + X}{X}\\ =&\dbinom{X + 1}{X} + \dbinom{X + 2}{X} + \dbinom{X + 3}{X} + \cdots + \dbinom{X + n}{X}\\ =&\dbinom{X + 1}{X + 1} + \dbinom{X + 1}{X} + \dbinom{X + 2}{X} + \dbinom{X + 3}{X} + \cdots + \dbinom{X + n}{X} - \dbinom{X + 1}{X + 1}\\ =&\dbinom{X + 2}{X + 1} + \dbinom{X + 2}{X} + \dbinom{X + 3}{X} + \cdots + \dbinom{X + n}{X} - \dbinom{X + 1}{X + 1}\\ =&\dbinom{X + 3}{X + 1} + \dbinom{X + 3}{X} + \cdots + \dbinom{X + n}{X} - \dbinom{X + 1}{X + 1}\\ \cdots\\ =&\dbinom{X + n}{X + 1} + \dbinom{X + n}{X} - \dbinom{X + 1}{X + 1}\\ =&\dbinom{X + n + 1}{X + 1} - \dbinom{X + 1}{X + 1}\\ =&\dbinom{X + n + 1}{X + 1} - 1\\ \end{aligned} $$ 好了,用Lucas定理就好了。 理论存在,实践开始。 Code: ```cpp #include <bits/stdc++.h> namespace VividCycle { #include <bits/stdc++.h> #define getchar gc #define putchar pc #define fu(i, l, r) for(int i = l; i <= r; ++i) #define fd(i, l, r) for(int i = l; i >= r; --i) #define fo(i, v) for(const auto& i : v) using namespace std; typedef __int128 ll; typedef unsigned long long ull; static char buffer[1 << 20 | 1]; static int outp = -1; void flush() {fwrite(buffer, 1, outp + 1, stdout), outp = -1;} void pc(const char& ch) {if(outp == (1 << 20)) flush(); buffer[++outp] = ch;} char gc() {static char ibuf[1 << 20], *p1 = ibuf, *p2 = ibuf; return p1 == p2 && (p2 = (p1 = ibuf) + fread(ibuf, 1, 1000010, stdin), p1 == p2) ? -1 : *p1++;} template<typename T> void read(T& x) {x = 0; int f = 1; char ch = getchar(); while(ch < '0' || ch > '9') f *= ((ch == '-') ? -1 : 1), ch = getchar(); while(ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar(); x *= f;} template<typename T, typename ...Args> void read(T& x, Args& ...args) {read(x), read(args...);} void write(const char& ch) {putchar(ch);} void write(const char s[]) {int len = strlen(s) - 1; fu(i, 0, len) putchar(s[i]);} void write(char s[]) {int len = strlen(s) - 1; fu(i, 0, len) putchar(s[i]);} template<typename T> void write(T x) {static char obuf[1 << 8]; static int p; p = 0; if(x < 0) x *= (putchar('-'), -1); if(!x) {putchar('0'); return;} while(x) obuf[++p] = x % 10 ^ 48, x /= 10; while(p) putchar(obuf[p--]);} template<typename T, typename ...Args> void write(T x, Args ...args) {write(x), write(args...);} } using namespace VividCycle; const int mod = 1000003; ll t, n, l, r, fact[mod], inv[mod]; ll ksm(ll x, ll y) { ll ret = 1; while(y) { if(y & 1) ret = ret * x % mod; x = x * x % mod; y >>= 1; } return ret; } ll c(ll n, ll m) { if(n < m) return 0; if(!m) return 1; return fact[n] * inv[m] % mod * inv[n - m] % mod; } ll lucas(ll n, ll m) { if(!m) return 1; return lucas(n / mod, m / mod) * c(n % mod, m % mod) % mod; } int main() { fact[0] = 1; fu(i, 1, mod - 1) fact[i] = fact[i - 1] * i % mod; inv[mod - 1] = ksm(fact[mod - 1], mod - 2); fd(i, mod - 1, 1) inv[i - 1] = inv[i] * i % mod; read(t); while(t--) { read(n, l, r); write((lucas(r - l + n + 1, r - l + 1) + mod - 1) % mod, '\n'); } flush(); return 0; } ```