日常刷题2025-2-21

日常刷题2025-2-21

C. Beautiful Sequence子序列计数问题

https://codeforces.com/contest/2069/problem/C

思路:线性DP

子序列计数的问题是一类典型的dp,我回头专门讲一下。大概就是:求子序列的DP,一般对于某个元素可以区分:选/不选,来做。求两个子序列可以区分:不选/选进序列1/选进序列2,三种转移。

代码

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

#if !defined(ONLINE_JUDGE) && defined(LOCAL)
#include "helper.h"
#else
#define dbg(...) ;
#define local_go_m(x) int c;cin>>c;while(c--)x()
#endif

constexpr int M = 998244353;

template<class T>
constexpr T power(T a, i64 b) {
    T res = 1;
    for (; b != 0; b /= 2, a *= a) {
        if (b & 1) {
            res *= a;
        }
    }
    return res;
}

template<int M>
struct ModInt {
public:
    constexpr ModInt() : x(0) {}

    template<std::signed_integral T>
    constexpr ModInt(T x_) {
        T v = x_ % M;
        if (v < 0) {
            v += M;
        }
        x = v;
    }

    constexpr int val() const {
        return x;
    }

    constexpr ModInt operator-() const {
        ModInt res;
        res.x = (x == 0 ? 0 : M - x);
        return res;
    }

    constexpr ModInt inv() const {
        return power(*this, M - 2);
    }

    constexpr ModInt &operator*=(const ModInt &rhs) &{
        x = i64(x) * rhs.val() % M;
        return *this;
    }

    constexpr ModInt &operator+=(const ModInt &rhs) &{
        x += rhs.val();
        if (x >= M) {
            x -= M;
        }
        return *this;
    }

    constexpr ModInt &operator-=(const ModInt &rhs) &{
        x -= rhs.val();
        if (x < 0) {
            x += M;
        }
        return *this;
    }

    constexpr ModInt &operator/=(const ModInt &rhs) &{
        return *this *= rhs.inv();
    }

    friend constexpr ModInt operator*(ModInt lhs, const ModInt &rhs) {
        lhs *= rhs;
        return lhs;
    }

    friend constexpr ModInt operator+(ModInt lhs, const ModInt &rhs) {
        lhs += rhs;
        return lhs;
    }

    friend constexpr ModInt operator-(ModInt lhs, const ModInt &rhs) {
        lhs -= rhs;
        return lhs;
    }

    friend constexpr ModInt operator/(ModInt lhs, const ModInt &rhs) {
        lhs /= rhs;
        return lhs;
    }

    friend constexpr std::istream &operator>>(std::istream &is, ModInt &a) {
        i64 i;
        is >> i;
        a = i;
        return is;
    }

    friend constexpr std::ostream &operator<<(std::ostream &os, const ModInt &a) {
        return os << a.val();
    }

    friend constexpr std::strong_ordering operator<=>(ModInt lhs, ModInt rhs) {
        return lhs.val() <=> rhs.val();
    }

private:
    int x;
};

using Z = ModInt<M>;

template<typename T>
struct Comb {
    std::vector<T> fac;
    std::vector<T> facInv;
    int n;

    Comb(int n_) {
        n = n_;
        fac.assign(n, T{});
        facInv.assign(n, T{});
        fac[0] = 1;
        for (int i = 1; i < n; i++) {
            fac[i] = fac[i - 1] * i;
        }
        for (int i = 0; i < n; i++) {
            facInv[i] = fac[i].inv();
        }
    }
};

constexpr int COMB_N = 300300;
Comb<Z> comb(COMB_N);

template<std::signed_integral T>
Z P(T n, T m) {
    assert(n >= 0 && m >= 0 && m <= n);
    if (n < comb.n) {
        return comb.fac[n] * comb.facInv[n - m];
    } else {
        T v = n, rnd = m;
        Z res = 1;
        while (rnd--) {
            res *= v--;
        }
        return res;
    }
}

template<std::signed_integral T>
Z C(T n, T m) {
    return P(n, m) * comb.facInv[m];
}

void go() {
    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) cin >> a[i];
    vector<Z> f(n, 0);
    int c1 = 0;
    Z res = 0;
    for (int i = 0; i < n; i++) {
        if (a[i] == 1) {
            if (i) f[i] = f[i - 1];
            c1++;
        } else if (a[i] == 3) {
            if (i) f[i] = f[i - 1];
            res += f[i];
        } else {
            if (i) f[i] = f[i - 1] * 2;
            f[i] += c1;
        }
    }
    dbg(f);
    cout << res << endl;
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    local_go_m(go);
    return 0;
}
posted @ 2025-02-21 13:34  califeee  阅读(18)  评论(0)    收藏  举报