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;
}
View Code

 

posted @ 2019-10-14 21:30  Mrzdtz220  阅读(119)  评论(0编辑  收藏  举报