CF-Educational Codeforces Round 83-D-Count the Arrays

题目传送门

sol:首先我们考虑在一个长度为$n$的序列里只有一个数出现了两次其他数都只出现了一次,那么在序列中出现过的数就有$n - 1$个。而这些数的范围是$[1, m]$,从$[1, m]$里选$n - 1$个不同的数的方案数为$C_{m}^{n - 1}$。这$n - 1$个数里最大的数不能作为出现两次的数,否则就没有峰值了,所以可以作为出现两次的数有$n - 2$个。再考虑这些数的排列,出现两次的数肯定要一个在峰值左边一个在峰值右边,除了出现两次的数和峰值以外还剩$n - 3$个数,这些数可以在峰值左边也可以在峰值右边,所以有$2^{n - 3}$种情况。最终的结果就是$C_{m}^{n - 1}*(n - 2)*(2^{n - 3})$。另外在特判一下$n$是2的情况,如果$n$是2又出现了一对重复的数是没有峰值的,所以结果一定是$0$。

  • 排列组合
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> PII;
    const int MOD = 998244353;
    int quick_pow(int n, int k) {
        int res = 1;
        while (k) {
            if (k & 1) res = 1LL * res * n % MOD;
            n = 1LL * n * n % MOD;
            k >>= 1;
        }
        return res % MOD;
    }
    int main() {
        int n, m;
        scanf("%d%d", &n, &m);
        if (n == 2) return puts("0") * 0;
        int ans = 1LL * (n - 2) * quick_pow(2, n - 3) % MOD;
        int tmp1 = 1, tmp2 = 1;
        for (int i = 1; i <= n - 1; i++) {
            tmp1 = 1LL * tmp1 * (m - i + 1) % MOD;
            tmp2 = 1LL * tmp2 * i % MOD;
        }
        ans = 1LL * ans * tmp1 % MOD;
        ans = 1LL * ans * quick_pow(tmp2, MOD - 2) % MOD;
        printf("%d\n", ans);
        return 0;
    }

     

posted @ 2020-03-10 12:59  Jathon-cnblogs  阅读(182)  评论(0编辑  收藏  举报