日常刷题2025-2-21
1.日常刷题2025-3-162.日常训练2025-1-23.日常训练2025-1-34.日常训练2025-1-55.日常训练2025-1-86.日常训练2025-1-117.日常训练2025-1-128.日常训练2025-1-139.日常训练2025-1-1410.日常训练2025-1-1511.日常训练2025-1-1612.日常训练2025-1-1713.日常训练2025-1-1814.日常训练2025-1-1915.日常训练2025-1-2116.日常训练2025-1-2217.日常刷题2025-1-2318.日常训练2025-1-2419.日常刷题2025-1-2520.日常刷题21.日常刷题2025-2-622.日常刷题2025-2-923.日常刷题2025-2-1424.日常刷题2025-2-1525.日常刷题2025-2-1726.日常刷题2025-2-20
27.日常刷题2025-2-21
28.日常刷题2025-2-2229.日常刷题2025-2-2430.日常刷题2025-2-2631.日常刷题2025-2-2732.日常刷题2025-2-2833.日常刷题2025-3-134.日常刷题2025-3-235.日常刷题2025-3-336.日常刷题2025-3-537.日常刷题2025-3-638.日常刷题2025-3-739.日常刷题2025-3-840.日常刷题2025-3-941.日常刷题2025-3-1042.日常刷题2023-3-1143.日常刷题2025-3-1344.非常棒的二分和DP日常刷题2025-2-21
C. Beautiful Sequence子序列计数问题
思路:线性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; }
本文作者:califeee
本文链接:https://www.cnblogs.com/califeee/p/18729058
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步