Submission #17079072


Source Code Expand

#include <bits/stdc++.h>
using i64 = long long;

constexpr i64 mod = 998244353;

std::vector<long long> fact, inv;

constexpr auto pow(long long x, long long n, const long long mod) {
    long long ret = 1;
    while(n > 0) {
        if ((n & 1) == 1) ret = (ret * x) % mod;
        x = (x * x) % mod;
        n >>= 1;
    }
    return ret;
}

constexpr auto inverse(const long long x, const long long p) {
    return pow(x, p - 2, p);
}

void init_factorial(const int n, const long long mod) {
    fact.resize(n + 1);
    inv.resize(n + 1);
    fact[0] = 1;
    for (long long i = 1; i <= n; i++) fact[i] = fact[i - 1] * i % mod;
    inv[n] = inverse(fact[n], mod);
    for (long long i = n; i > 0; i--) inv[i - 1] = inv[i] * i % mod;
}

std::vector<i64> roots, rootsinv;

void calc_roots(const int n) {
    int sz = 0;
    while ((1 << sz) <= n) sz++;
    roots.resize(sz);
    rootsinv.resize(sz);

    for (int i = 1; i < sz; i++) roots[i] = pow(3, (mod - 1) / (1 << i), mod);
    for (int i = 1; i < sz; i++) rootsinv[i] = inverse(roots[i], mod);
}

void ntt(std::vector<i64> &a, bool rev = false) {
    const i64 n = a.size();
    if (roots.empty()) calc_roots(100100);

    for (int i = 0, j = 1; j < n - 1; j++) {
        for (int k = n >> 1; k > (i ^= k); k >>= 1);
        if (j < i) std::swap(a[i], a[j]);
    }

    for (int mi = 1; (1 << mi) <= n; mi++) {
        const int m = 1 << mi;
        const i64 cc = rev ? rootsinv[mi] : roots[mi];

        for (int i = 0; i < n; i += m) {
            i64 w = 1;
            for (int j = i, k = i + m / 2; k < i + m; j++, k++) {
                i64 t1 = a[j], t2 = w * a[k] % mod;
                a[j] = (t1 + t2) % mod;
                a[k] = (t1 + mod - t2) % mod;
                w = w * cc % mod;
            }
        }
    }

    if (rev) {
        const i64 rv = inverse(n, mod);
        for (int i = 0; i < n; i++) a[i] = a[i] * rv % mod;
    }
}

std::vector<i64> multiply(std::vector<i64> f, std::vector<i64> g) {
    int maxindex = f.size() + g.size() + 1;
    int s = 1;
    while (s < maxindex) s *= 2;
    f.resize(s);
    g.resize(s);

    ntt(f);
    ntt(g);

    for (int i = 0; i < f.size(); i++) f[i] = f[i] * g[i] % mod;
    ntt(f, true);
    while (f.size() > 1 && f.back() == 0) f.pop_back();
    return f;
}

struct Comp {
    bool operator()(const std::vector<i64> &lhs, const std::vector<i64> &rhs) const {
        return lhs.size() < rhs.size();
    }
};

int main() {
    int n;
    std::cin >> n;
    init_factorial(2 * n, mod);
    std::vector<i64> cnt(100100);
    for (int i = 0; i < 2 * n; i++) {
        int a;
        std::cin >> a;
        cnt[a]++;
    }

    constexpr i64 i2 = inverse(2, mod);

    std::multiset<std::vector<i64>, Comp> ss;
    for (const auto e : cnt) {
        if (!e) continue;
        std::vector<i64> co;
        i64 q = 1;
        for (int i = 0; 2 * i <= e; i++) {
            const i64 c = fact[e] * inv[e - 2 * i] % mod * inv[i] % mod * q % mod;
            co.push_back(c);
            q = q * i2 % mod;
        }
        ss.insert(co);
    }

    while (ss.size() > 1) {
        const auto f = std::move(ss.extract(ss.begin()).value());
        const auto g = std::move(ss.extract(ss.begin()).value());
        const auto &&h = multiply(f, g);
        ss.insert(h);
    }

    const auto &v = *ss.begin();
    i64 d = inverse(pow(2, n, mod), mod), ret = 0;
    for (int i = 0; i < v.size(); i++) {
        const i64 x = fact[2 * (n - i)] * d % mod * inv[n - i] % mod;
        if (i % 2 == 0) ret = (ret + x * v[i] % mod) % mod;
        else ret = (ret + mod - x * v[i] % mod) % mod;
        d = d * 2 % mod;
    }

    std::cout << ret << std::endl;

    return 0;
}

Submission Info

Submission Time
Task F - Heights and Pairs
User CharlotteL
Language C++ (GCC 9.2.1)
Score 600
Code Size 3830 Byte
Status AC
Exec Time 145 ms
Memory 14604 KiB

Compile Error

./Main.cpp: In function ‘std::vector<long long int> multiply(std::vector<long long int>, std::vector<long long int>)’:
./Main.cpp:83:23: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<long long int>::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
   83 |     for (int i = 0; i < f.size(); i++) f[i] = f[i] * g[i] % mod;
      |                     ~~^~~~~~~~~~
./Main.cpp: In function ‘int main()’:
./Main.cpp:130:23: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<long long int>::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  130 |     for (int i = 0; i < v.size(); i++) {
      |                     ~~^~~~~~~~~~

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 600 / 600
Status
AC × 2
AC × 23
Set Name Test Cases
Sample example0.txt, example1.txt
All 000.txt, 001.txt, 002.txt, 003.txt, 004.txt, 005.txt, 006.txt, 007.txt, 008.txt, 009.txt, 010.txt, 011.txt, 012.txt, 013.txt, 014.txt, 015.txt, 016.txt, 017.txt, 018.txt, 019.txt, 020.txt, example0.txt, example1.txt
Case Name Status Exec Time Memory
000.txt AC 119 ms 14604 KiB
001.txt AC 35 ms 6132 KiB
002.txt AC 46 ms 7496 KiB
003.txt AC 50 ms 7308 KiB
004.txt AC 48 ms 7288 KiB
005.txt AC 54 ms 7480 KiB
006.txt AC 51 ms 7476 KiB
007.txt AC 61 ms 7616 KiB
008.txt AC 66 ms 7568 KiB
009.txt AC 67 ms 7584 KiB
010.txt AC 71 ms 7880 KiB
011.txt AC 81 ms 7552 KiB
012.txt AC 88 ms 7624 KiB
013.txt AC 90 ms 7856 KiB
014.txt AC 101 ms 8288 KiB
015.txt AC 102 ms 8048 KiB
016.txt AC 110 ms 8472 KiB
017.txt AC 119 ms 8376 KiB
018.txt AC 124 ms 8400 KiB
019.txt AC 134 ms 8884 KiB
020.txt AC 145 ms 10484 KiB
example0.txt AC 3 ms 3872 KiB
example1.txt AC 3 ms 3876 KiB