BZOJ4403: 序列统计
[传送门]
一个单调不减的序列,如果在每个位置取的数都加上对应位置的值,这样就是严格单调递增的了。
如果 [1, 1, 2, 2, 3]就会变成 [2, 3, 5, 6, 8]
就相当于在某个值域里取一些不重复的数了,具体这个值域就是[L + 1 , R + n]。
但其实此时跟值域具体的值无关了,只跟值域的长度有关。
值域长度为 $n + R - L$ , 那么取长度为 $n$ 的取法就为 $C ^{n} _{n + R - L}$
答案为$\sum ^{n} _{i = 1} C _{R - L + i} ^{i}$
设 $ m = R - L $
$ \sum ^{n} _{i = 0} C _{m + i} ^{i} = C _{m + n + 1} ^{n} $
所以答案就是 $ C _{m + n + 1} ^ {n} - 1 $
再用一下Lucas定理就可以了。
#include <bits/stdc++.h> #define ll long long using namespace std; const int MOD = 1e6 + 3; const int N = 1e6 + 7; int fac[N], inv[N]; int qp(int a, int b = MOD - 2) { int ans = 1; while (b) { if (b & 1) ans = 1LL * ans * a % MOD; a = 1LL * a * a % MOD; b >>= 1; } return ans; } int C(int n, int m) { if (n < m) return 0; return 1LL * fac[n] * inv[m] * inv[n - m] % MOD; } int Lucas(int n, int m) { if (n < m) return 0; return m ? 1LL * Lucas(n / MOD, m / MOD) * C(n % MOD, m % MOD) % MOD : 1; } inline int M(int a) { if (a < 0) a += MOD; if (a >= MOD) a -= MOD; return a; } int main() { for (int i = fac[0] = 1; i < MOD; i++) fac[i] = 1LL * i * fac[i - 1] % MOD; inv[MOD - 1] = qp(fac[MOD - 1]); for (int i = MOD - 2; i >= 0; i--) inv[i] = 1LL * inv[i + 1] * (i + 1) % MOD; int T; scanf("%d", &T); while (T--) { int n, l, r; scanf("%d%d%d", &n, &l, &r); printf("%d\n", M(Lucas(n + (r - l + 1), r - l + 1) - 1)); } return 0; }