QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#282994#6410. Classical DP ProblemjrjyyWA 0ms3752kbC++205.2kb2023-12-13 17:20:002023-12-13 17:20:00

Judging History

你现在查看的是最新测评结果

  • [2023-12-13 17:20:00]
  • 评测
  • 测评结果:WA
  • 用时:0ms
  • 内存:3752kb
  • [2023-12-13 17:20:00]
  • 提交

answer

#include <bits/stdc++.h>

using i64 = long long;

template <typename T>
constexpr T power(T a, i64 b) {
    T c{1};
    while (b) {
        if (b % 2) {
            c *= a;
        }
        a *= a;
        b /= 2;
    }
    return c;
}

template <int P>
struct MInt {
    int x;
    constexpr MInt() : x{} {}
    constexpr MInt(i64 x_) : x{up(x_ % getMod())} {}
    constexpr static MInt fromNormed(int x) {
        MInt v{};
        v.x = x;
        return v;
    }

    static int Mod;
    constexpr static int getMod() {
        return P > 0 ? P : Mod;
    }
    constexpr static void setMod(int Mod_) {
        Mod = Mod_;
    }

    inline constexpr static int up(int x) {
        if (x < 0) {
            x += getMod();
        }
        return x;
    }
    inline constexpr static int down(int x) {
        if (x >= getMod()) {
            x -= getMod();
        }
        return x;
    }
    inline constexpr static int norm(int x) {
        return up(down(x));
    }

    inline constexpr int val() const {
        return x;
    }
    inline explicit constexpr operator int() const {
        return val();
    }
    inline constexpr MInt operator-() const {
        MInt res;
        res.x = norm(getMod() - x);
        return res;
    }
    inline constexpr MInt inv() const {
        assert(x != 0);
        return power(*this, getMod() - 2);
    }
    inline constexpr MInt &operator+=(MInt rhs) {
        x = down(x + rhs.x);
        return *this;
    }
    inline constexpr MInt &operator-=(MInt rhs) {
        x = up(x - rhs.x);
        return *this;
    }
    inline constexpr MInt &operator*=(MInt rhs) {
        x = 1ll * x * rhs.x % getMod();
        return *this;
    }
    inline constexpr MInt &operator/=(MInt rhs) {
        return *this *= rhs.inv();
    }
    friend inline constexpr MInt operator+(MInt lhs, MInt rhs) {
        return lhs += rhs;
    }
    friend inline constexpr MInt operator-(MInt lhs, MInt rhs) {
        return lhs -= rhs;
    }
    friend inline constexpr MInt operator*(MInt lhs, MInt rhs) {
        return lhs *= rhs;
    }
    friend inline constexpr MInt operator/(MInt lhs, MInt rhs) {
        return lhs /= rhs;
    }
    friend inline constexpr bool operator==(MInt lhs, MInt rhs) {
        return lhs.val() == rhs.val();
    }
    friend inline constexpr bool operator!=(MInt lhs, MInt rhs) {
        return lhs.val() != rhs.val();
    }
    friend constexpr std::istream &operator>>(std::istream &is, MInt &a) {
        i64 x = 0;
        is >> x;
        a = MInt(x);
        return is;
    }
    friend constexpr std::ostream &operator<<(std::ostream &os, const MInt &a) {
        return os << a.val();
    }
};

template <int P>
int MInt<P>::Mod = P;
template <>
int MInt<0>::Mod = 998244353;

template <int V, int P>
constexpr MInt<P> CInv = MInt<P>(V).inv();

constexpr int P = 998244353;
using Z = MInt<P>;

template <int P>
struct IComb {
    using Z = MInt<P>;
    int n;
    std::vector<Z> fac_, ifac_, inv_;

    IComb() : n(0), fac_{1}, ifac_{1}, inv_{0} {}
    IComb(int n) : IComb{} {
        init(n);
    }
    void init(int m) {
        if (m <= n) {
            return;
        }
        assert(m < Z::getMod());
        fac_.resize(m + 1);
        ifac_.resize(m + 1);
        inv_.resize(m + 1);

        for (int i = n + 1; i <= m; ++i) {
            fac_[i] = fac_[i - 1] * i;
        }
        ifac_[m] = fac_[m].inv();
        for (int i = m; i > n + 1; --i) {
            ifac_[i - 1] = ifac_[i] * i;
        }
        for (int i = m; i > n; --i) {
            inv_[i] = ifac_[i] * fac_[i - 1];
        }
        n = m;
    }

    Z fac(int m) {
        if (n < m) {
            init(2 * m);
        }
        return fac_[m];
    }
    Z ifac(int m) {
        if (n < m) {
            init(2 * m);
        }
        return ifac_[m];
    }
    Z inv(int m) {
        if (n < m) {
            init(2 * m);
        }
        return inv_[m];
    }
    Z binom(int n, int m) {
        if (n < m || m < 0) {
            return Z{};
        }
        return fac(n) * ifac(m) * ifac(n - m);
    }
};

using Comb = IComb<P>;
Comb comb;

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    int n;
    std::cin >> n;

    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }
    
    std::reverse(a.begin(), a.end());

    int k = 0;
    while (a[k] >= k + 1) {
        ++k;
    }

    auto work = [&](std::vector<int> a) -> Z {
        a.push_back(0);
        std::vector<Z> f(a[k] + 1), g;
        f[a[k]] = 1;
        for (int i = 0; i < n; ++i) {
            g.assign(a[k] + 1, 0);
            for (int j = 0; j <= a[k]; ++j) {
                g[j] += f[j] * (a[i] - j);
                if (j > 0) {
                    g[j - 1] += f[j] * j;
                }
            }
            f = g;
        }
        return f[0];
    };

    std::vector<int> b(n);
    for (int i = 0; i < n; ++i) {
        b[a[i] - 1] += 1;
    }
    for (int i = n - 1; i > 0; --i) {
        b[i - 1] += b[i];
    }
    Z ans = work(a) + work(b) - comb.fac(n);

    std::cout << k << " " << ans << "\n";

    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 3752kb

input:

3
1 2 3

output:

2 6

result:

ok 2 number(s): "2 6"

Test #2:

score: 0
Accepted
time: 0ms
memory: 3568kb

input:

1
1

output:

1 1

result:

ok 2 number(s): "1 1"

Test #3:

score: -100
Wrong Answer
time: 0ms
memory: 3640kb

input:

2
1 1

output:

1 998244352

result:

wrong answer 2nd numbers differ - expected: '2', found: '998244352'