题目-序列统计

问题分析
尝试枚举序列长度 k k k, 当 k k k固定之后, 有多少个单调不下降序列, 并且所有数字在 [ L , R ] [L, R] [L,R]之间
因为数字之间大小是相对的, 可以映射到 [ 0 , R − L ] [0, R - L] [0,R−L], 并且数字是单调不下降的
那么有序列
0 ≤ a 1 ≤ a 2 . . . ≤ a k ≤ R − L 0 \le a_1 \le a_2 ... \le a_k \le R - L 0≤a1≤a2...≤ak≤R−L
令 x 1 = a 1 x_1 = a_1 x1=a1, x 2 = a 2 − a 1 x_2 = a_2 - a_1 x2=a2−a1, x k = a k − a k − 1 x_k = a_k - a_{k - 1} xk=ak−ak−1
问题就转化成了 x i ≥ 0 x_i \ge 0 xi≥0条件下
x 1 + x 2 + . . . + x k ≤ R − L x_1 + x_2 + ... + x_k \le R - L x1+x2+...+xk≤R−L
不定方程的非负整数解的个数
因为每个 x i ≥ 0 x_i \ge 0 xi≥0不好操作, 令 y i = x i + 1 y_i = x_i + 1 yi=xi+1, 其中 y i ≥ 1 y_i \ge 1 yi≥1
y 1 + y 2 + . . . + y k ≤ R − L + k y_1 + y_2 + ... + y_k \le R - L + k y1+y2+...+yk≤R−L+k
如果是等式, 那么 k k k个变量需要放置 k − 1 k - 1 k−1个隔板, 但是这里是 ≤ \le ≤, 因此可以放置 k k k个隔板
也就是说最后一个隔板到最后一个小球的长度是 R − L + k − t R - L + k - t R−L+k−t, t t t是实际的和
当前 k k k的方案数 C R − L + k k C_{R - L + k} ^ k CR−L+kk
那么答案是 ∑ k = 1 N C R − L + k k \sum _{k = 1} ^ N C_{R - L + k} ^ k ∑k=1NCR−L+kk, 令 m = R − L m = R - L m=R−L
求和展开得到
C m + 1 1 + C m + 2 2 + . . . + C m + n n C_{m + 1} ^ 1 + C_{m + 2} ^ 2 +... + C_{m + n} ^ n Cm+11+Cm+22+...+Cm+nn
由组合恒等式 C a b = C a a − b C_a ^ b = C_a ^ {a - b} Cab=Caa−b得到
C m + 1 m + C m + 2 m + . . . + C m + n m C_{m + 1} ^ m + C_{m + 2} ^ m + ... + C_{m + n} ^ m Cm+1m+Cm+2m+...+Cm+nm
由组合恒等式 C a b = C a − 1 b + C a − 1 b − 1 C_a ^ b = C_{a - 1} ^ b + C_{a - 1} ^ {b - 1} Cab=Ca−1b+Ca−1b−1得到
C m + 1 m + 1 + C m + 1 m + C m + 2 m + . . . + C m + n m − 1 C_{m + 1} ^ {m + 1} + C_{m + 1} ^ m + C_{m + 2} ^ m + ... + C_{m + n} ^ m - 1 Cm+1m+1+Cm+1m+Cm+2m+...+Cm+nm−1
整理得到
C m + 2 m + 1 + C m + 2 m + . . . + C m + n m − 1 C_{m + 2} ^ {m + 1} + C_{m + 2} ^ m + ... + C_{m + n} ^ m - 1 Cm+2m+1+Cm+2m+...+Cm+nm−1
两项两项合并, 最终得到
C m + n m + 1 + C m + n m − 1 = C m + n + 1 m + 1 − 1 C_{m + n} ^ {m + 1} + C_{m + n} ^ m - 1 = C_{m + n + 1} ^ {m + 1} - 1 Cm+nm+1+Cm+nm−1=Cm+n+1m+1−1
最终的结果
a n s = C R − L + N + 1 R − L + 1 − 1 ans = C_{R - L + N + 1} ^ {R - L + 1} - 1 ans=CR−L+N+1R−L+1−1
算法步骤
线性方程和线性不定方程的正整数解的个数都可以使用隔板法解决
观察数据范围, R , L ≤ 1 0 9 R, L \le 10 ^ 9 R,L≤109比较大, 但是取模的数字很小 1 0 6 + 3 10 ^ 6 + 3 106+3, 可以使用 l u c a s lucas lucas定理计算组合数
代码实现
注意计算阶乘的逆元的时候 i i i从 1 1 1开始循环, 并且在 g e t get get函数过程中需要进行取模
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e6 + 10, MOD = 1e6 + 3;
int n, l, r;
LL fact[N], infact[N];
LL q_pow(LL a, LL b, LL mod) {
LL ans = 1;
a %= mod;
while (b) {
if (b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
void init() {
fact[0] = 1;
infact[0] = q_pow(fact[0], MOD - 2, MOD);
for (int i = 1; i < N; ++i) {
fact[i] = fact[i - 1] % MOD * i % MOD;
infact[i] = q_pow(fact[i], MOD - 2, MOD);
}
}
LL get(LL a, LL b) {
if (a < b) return 0;
LL ans = fact[a] % MOD * infact[b] % MOD * infact[a - b] % MOD;
return ans;
}
LL lucas(LL a, LL b) {
if (b == 0) return 1;
return lucas(a / MOD, b / MOD) * get(a % MOD, b % MOD) % MOD;
}
void solve() {
cin >> n >> l >> r;
LL a = r - l + n + 1;
LL b = r - l + 1;
LL ans = lucas(a, b) - 1;
ans = (ans % MOD + MOD) % MOD;
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
init();
int T;
cin >> T;
while (T--) solve();
return 0;
}

京公网安备 11010502036488号