CodeForces -. 1312D Count the Arrays combinatorics

CodeForces - 1312D. Count the Arrays

Address original title:

http://codeforces.com/contest/1312/problem/D

The basic meaning of the questions:

Calculation of the number of array meet the following conditions:

  1. Array has n elements
  2. Array element value between 1 - m
  3. For each array has one and only one pair of equal elements (I am an English mental retardation, this has not exactly get to know)
  4. There is an array meet a strictly increasing at position i left i, the right strictly decreasing

The answer modulo 998 244 353;

The basic idea:

  1. We are looking for simultaneously satisfy the condition (3) (4) of the array, as long as we [1, m] to find the pick n - 1 number of them strictly ascending;
  2. Then, in order to satisfy the condition (3) again in addition to the highest i.e. that the remaining n - 2 a pick as the one on the right side in duplicate;
  3. Finally, the remaining n-3 may be arbitrarily picked number where the i-th on the right side (i = 1,2,3, ..., n-3).

So to sum up the answer:

   mod_comb(m, n-1,mod) * mod_comb(n - 2, 1,mod) * 2 ^ (n-3) % mod

Reference Code:

#include <bits/stdc++.h>
using namespace std;
#define IO std::ios::sync_with_stdio(false)
#define int long long
#define INF 0x3f3f3f3f

const int maxn = 2e5+10;
int fact[maxn];
inline int qsm(int x,int n,int mod) {
    int res = 1;
    while (n > 0) {
        if (n & 1) res = res * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return res;
}
inline int extgcd(int a,int b,int &x,int &y) {
    int d = a;
    if (b != 0) {
        d = extgcd(b, a % b, y, x);
        y -= (a / b) * x;
    } else {
        x = 1;
        y = 0;
    }
    return d;
}
inline int mod_inverse(int a,int m) {
    int x, y;
    extgcd(a, m, x, y);
    return (m + x % m) % m;
}
inline int mod_fact(int n,int p,int &e) {
    e = 0;
    if (n == 0) return 1;
    int res = mod_fact(n / p, p, e);
    e += n / p;

    if (n / p % 2 != 0) return res * (p - fact[n % p] % p);
    return res * fact[n % p] % p;
}
inline int mod_comb(int n,int k,int p) {
    if (n < 0 || k < 0 || n < k) return 0;
    int e1, e2, e3;
    int a1 = mod_fact(n, p, e1), a2 = mod_fact(k, p, e2), a3 = mod_fact(n - k, p, e3);
    if (e1 > e2 + e3) return 0;
    return a1 * mod_inverse(a2 * a3 % p, p) % p;
}
const int mod = 998244353;
int n,m;
signed main() {
    IO;
    fact[0] = 0, fact[1] = 1;
    for (int i = 2; i <= maxn; i++) fact[i] = fact[i - 1] * i % mod;
    cin >> n >> m;
    if (n == 2) {
        cout << 0 << endl;
        return 0;
    }
    int ans = mod_comb(m, n - 1, mod);
    ans %= mod;
    ans *= n - 2;
    ans %= mod;
    ans *= qsm(2, n - 3, mod);
    ans %= mod;
    cout << ans << endl;
    return 0;
}

Published 12 original articles · won praise 5 · Views 485

Guess you like

Origin blog.csdn.net/weixin_44164153/article/details/104794987