QOJ.ac

QOJ

详细

Extra Test:

Time Limit Exceeded

input:

500
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ...

output:


result:


ID题目提交者结果用时内存语言文件大小提交时间测评时间
#914233#10111. Dividing Chainsthinking (Fedor Romashov, Alexey Mikhnenko, Gimran Abdullin)TL 113ms5376kbC++207.4kb2025-02-25 03:22:452025-02-25 03:28:21

answer

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ld = long double;

#define all(a) begin(a), end(a)
#define len(a) int((a).size())

#ifdef LOCAL
    #include "debug.h"
#else
    #define dbg(...)
    #define dprint(...)
    #define debug if constexpr (false)
#endif // LOCAL

/*
 ! WARNING: MOD must be prime if you use division or .inv().
 ! WARNING: 2 * (MOD - 1) must be smaller than INT_MAX
 * Use .value to get the stored value.
 */
template<typename T>
int normalize(T value, int mod) {
    if (value < -mod || value >= 2 * mod) value %= mod;
    if (value < 0) value += mod;
    if (value >= mod) value -= mod;
    return value;
}

template<int mod>
struct static_modular_int {
    static_assert(mod - 2 <= std::numeric_limits<int>::max() - mod, "2(mod - 1) <= INT_MAX");
    using mint = static_modular_int<mod>;

    int value;

    static_modular_int() : value(0) {}
    static_modular_int(const mint &x) : value(x.value) {}

    template<typename T, typename U = std::enable_if_t<std::is_integral<T>::value>>
    static_modular_int(T value) : value(normalize(value, mod)) {}

    static constexpr int get_mod() {
		return mod;
	}

    template<typename T>
    mint power(T degree) const {
        mint prod = 1, a = *this;
        for (; degree > 0; degree >>= 1, a *= a)
            if (degree & 1)
                prod *= a;

        return prod;
    }

    mint inv() const {
        return power(mod - 2);
    }

    mint& operator=(const mint &x) {
        value = x.value;
        return *this;
    }

    mint& operator+=(const mint &x) {
        value += x.value;
        if (value >= mod) value -= mod;
        return *this;
    }

    mint& operator-=(const mint &x) {
        value -= x.value;
        if (value < 0) value += mod;
        return *this;
    }

    mint& operator*=(const mint &x) {
        value = int64_t(value) * x.value % mod;
        return *this;
    }

    mint& operator/=(const mint &x) {
        return *this *= x.inv();
    }

    friend mint operator+(const mint &x, const mint &y) {
        return mint(x) += y;
    }

    friend mint operator-(const mint &x, const mint &y) {
        return mint(x) -= y;
    }

    friend mint operator*(const mint &x, const mint &y) {
        return mint(x) *= y;
    }

    friend mint operator/(const mint &x, const mint &y) {
        return mint(x) /= y;
    }

    mint& operator++() {
        ++value;
        if (value == mod) value = 0;
        return *this;
    }

    mint& operator--() {
        --value;
        if (value == -1) value = mod - 1;
        return *this;
    }

    mint operator++(int) {
        mint prev = *this;
        value++;
        if (value == mod) value = 0;
        return prev;
    }

    mint operator--(int) {
        mint prev = *this;
        value--;
        if (value == -1) value = mod - 1;
        return prev;
    }

    mint operator-() const {
        return mint(0) - *this;
    }

    bool operator==(const mint &x) const {
        return value == x.value;
    }

    bool operator!=(const mint &x) const {
        return value != x.value;
    }

    bool operator<(const mint &x) const {
        return value < x.value;
    }

    template<typename T>
    explicit operator T() {
        return value;
    }

    friend std::istream& operator>>(std::istream &in, mint &x) {
        std::string s;
        in >> s;
        x = 0;
        bool neg = s[0] == '-';
        for (const auto c : s)
            if (c != '-')
                x = x * 10 + (c - '0');

        if (neg)
            x *= -1;

        return in;
    }

    friend std::ostream& operator<<(std::ostream &out, const mint &x) {
        return out << x.value;
    }

    static int primitive_root() {
        if constexpr (mod == 1'000'000'007)
            return 5;
        if constexpr (mod == 998'244'353)
            return 3;
        if constexpr (mod == 786433)
            return 10;

        static int root = -1;
        if (root != -1)
            return root;

        std::vector<int> primes;
        int value = mod - 1;
        for (int i = 2; i * i <= value; i++)
            if (value % i == 0) {
                primes.push_back(i);
                while (value % i == 0)
                    value /= i;
            }

        if (value != 1)
            primes.push_back(value);

        for (int r = 2;; r++) {
            bool ok = true;
            for (auto p : primes)
                if ((mint(r).power((mod - 1) / p)).value == 1) {
                    ok = false;
                    break;
                }

            if (ok)
                return root = r;
        }
    }
};

// constexpr int MOD = 1'000'000'007;
constexpr int MOD = 998'244'353;
using mint = static_modular_int<MOD>;

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

    int n;
    cin >> n;
    vector<int> a(n);
    for (auto &x : a) {
        cin >> x;
    }
    
    vector f(n, vector<mint>(n)); // both orders are valid
    vector g(n, vector<mint>(n)); // at least one order is valid

    for (int d = 0; d < n; d++) {
        for (int l = 0; l + d < n; l++) {
            int r = l + d;
            if (a[l] == a[r]) {
                f[l][r] = g[l][r] = 1;
                continue;
            }

            g[l][r] += g[l + 1][r] * 2;
            for (int m = l + 1; m < r; m++) {
                g[l][r] += (g[l][m] - f[l][m]) * g[m + 1][r];
            }

            int cnt_mx = 0;
            while (a[r - cnt_mx] == a[r]) {
                cnt_mx++;
            }
            int cnt_mn = 0;
            while (a[l + cnt_mn] == a[l]) {
                cnt_mn++;
            }

            { // mx mx mx .... mx mx mx
                auto place = [&](int left, int right) -> mint {
                    if (left + right > cnt_mx) {
                        return 0;
                    }
                    return g[l][r - left - right];
                };

                for (int left = 1; left < cnt_mx; left++) {
                    for (int right = 1; left + right <= cnt_mx; right++) {
                        mint ways = 0;
                        ways += place(left, right);
                        ways -= place(left + 1, right);
                        ways -= place(left, right + 1);
                        ways += place(left + 1, right + 1);
                        f[l][r] += ways;
                    }
                }
            }

            { // mn mn mn .... mn mn mn
                auto place = [&](int left, int right) -> mint {
                    if (left + right > cnt_mn) {
                        return 0;
                    }
                    return g[l + left + right][r];
                };

                for (int left = 1; left < cnt_mn; left++) {
                    for (int right = 1; left + right <= cnt_mn; right++) {
                        mint ways = 0;
                        ways += place(left, right);
                        ways -= place(left + 1, right);
                        ways -= place(left, right + 1);
                        ways += place(left + 1, right + 1);
                        f[l][r] += ways;
                    }
                }
            }

            g[l][r] -= f[l][r];
        }
    }

    dbg(f);
    dbg(g);

    cout << g[0][n - 1] << '\n';
    // cout << f[0][n - 1] << '\n';
}