Removing People 题解
前言
题意简述
每个人面对的方向由长度为
重复
定义从
求
题目分析
期望类题目,我们学过的算法好像只有 DP 吧?考虑 DP。状态如何设计呢?移除一个人,难道我们要把
加入
我们注意到,对于
考虑区间 DP。设
那就别记期望了吧,把期望变成价值和比上方案数。方案数显然是
先来考虑
说了这么多,其实就是一个转移方程:
选择
注意到,之所以我一直避免
DP 初值考虑相邻的两项的
时间复杂度:
代码
展开取模板子
namespace Mod_Int_Class { template <typename T, typename _Tp> constexpr bool in_range(_Tp val) { return std::numeric_limits<T>::min() <= val && val <= std::numeric_limits<T>::max(); } template <typename _Tp, typename = std::enable_if_t<std::is_integral<_Tp>::value>> static constexpr inline bool is_prime(_Tp val) { if (val < 2) return false; for (_Tp i = 2; i * i <= val; ++i) if (val % i == 0) return false; return true; } template <auto _mod = 998244353, typename T = int, typename S = long long> class Mod_Int { static_assert(in_range<T>(_mod), "mod must in the range of type T."); static_assert(std::is_integral<T>::value, "type T must be an integer."); static_assert(std::is_integral<S>::value, "type S must be an integer."); public: constexpr Mod_Int() noexcept = default; template <typename _Tp, typename = std::enable_if_t<std::is_integral<_Tp>::value>> constexpr Mod_Int(_Tp v) noexcept: val(0) { if (0 <= T(v) && T(v) < mod) val = v; else val = (T(v) % mod + mod) % mod; } constexpr T const& raw() const { return this -> val; } static constexpr T mod = _mod; template <typename _Tp, typename = std::enable_if_t<std::is_integral<_Tp>::value>> constexpr friend Mod_Int pow(Mod_Int a, _Tp p) { return a ^ p; } constexpr friend Mod_Int sub(Mod_Int a, Mod_Int b) { return a - b; } constexpr friend Mod_Int& tosub(Mod_Int& a, Mod_Int b) { return a -= b; } constexpr friend Mod_Int add(Mod_Int a) { return a; } template <typename... args_t> constexpr friend Mod_Int add(Mod_Int a, args_t... args) { return a + add(args...); } constexpr friend Mod_Int mul(Mod_Int a) { return a; } template <typename... args_t> constexpr friend Mod_Int mul(Mod_Int a, args_t... args) { return a * mul(args...); } template <typename... args_t> constexpr friend Mod_Int& toadd(Mod_Int& a, args_t... b) { return a = add(a, b...); } template <typename... args_t> constexpr friend Mod_Int& tomul(Mod_Int& a, args_t... b) { return a = mul(a, b...); } template <T __mod = mod, typename = std::enable_if_t<is_prime(__mod)>> static constexpr inline T inv(T a) { assert(a != 0); return _pow(a, mod - 2); } constexpr Mod_Int& operator + () const { return *this; } constexpr Mod_Int operator - () const { return _sub(0, val); } constexpr Mod_Int inv() const { return inv(val); } constexpr friend inline Mod_Int operator + (Mod_Int a, Mod_Int b) { return _add(a.val, b.val); } constexpr friend inline Mod_Int operator - (Mod_Int a, Mod_Int b) { return _sub(a.val, b.val); } constexpr friend inline Mod_Int operator * (Mod_Int a, Mod_Int b) { return _mul(a.val, b.val); } constexpr friend inline Mod_Int operator / (Mod_Int a, Mod_Int b) { return _mul(a.val, inv(b.val)); } template <typename _Tp, typename = std::enable_if_t<std::is_integral<_Tp>::value>> constexpr friend inline Mod_Int operator ^ (Mod_Int a, _Tp p) { return _pow(a.val, p); } constexpr friend inline Mod_Int& operator += (Mod_Int& a, Mod_Int b) { return a = _add(a.val, b.val); } constexpr friend inline Mod_Int& operator -= (Mod_Int& a, Mod_Int b) { return a = _sub(a.val, b.val); } constexpr friend inline Mod_Int& operator *= (Mod_Int& a, Mod_Int b) { return a = _mul(a.val, b.val); } constexpr friend inline Mod_Int& operator /= (Mod_Int& a, Mod_Int b) { return a = _mul(a.val, inv(b.val)); } template <typename _Tp, typename = std::enable_if_t<std::is_integral<_Tp>::value>> constexpr friend inline Mod_Int& operator ^= (Mod_Int& a, _Tp p) { return a = _pow(a.val, p); } constexpr friend inline bool operator == (Mod_Int a, Mod_Int b) { return a.val == b.val; } constexpr friend inline bool operator != (Mod_Int a, Mod_Int b) { return a.val != b.val; } constexpr Mod_Int& operator ++ () { this -> val + 1 == mod ? this -> val = 0 : ++this -> val; return *this; } constexpr Mod_Int& operator -- () { this -> val == 0 ? this -> val = mod - 1 : --this -> val; return *this; } constexpr Mod_Int operator ++ (int) { Mod_Int res = *this; this -> val + 1 == mod ? this -> val = 0 : ++this -> val; return res; } constexpr Mod_Int operator -- (int) { Mod_Int res = *this; this -> val == 0 ? this -> val = mod - 1 : --this -> val; return res; } friend std::istream& operator >> (std::istream& is, Mod_Int<mod, T, S>& x) { T ipt; return is >> ipt, x = ipt, is; } friend std::ostream& operator << (std::ostream& os, Mod_Int<mod, T, S> x) { return os << x.val; } protected: T val; static constexpr inline T _add(T a, T b) { return a >= mod - b ? a + b - mod : a + b; } static constexpr inline T _sub(T a, T b) { return a < b ? a - b + mod : a - b; } static constexpr inline T _mul(T a, T b) { return static_cast<S>(a) * b % mod; } template <typename _Tp, typename = std::enable_if_t<std::is_integral<_Tp>::value>> static constexpr inline T _pow(T a, _Tp p) { T res = 1; for (; p; p >>= 1, a = _mul(a, a)) if (p & 1) res = _mul(res, a); return res; } }; using mint = Mod_Int<>; constexpr mint operator ""_m (unsigned long long x) { return mint(x); } constexpr mint operator ""_mod (unsigned long long x) { return mint(x); } }
#include <cstdio> #include <iostream> #include <limits> using namespace std; using namespace Mod_Int_Class; const int N = 310; int n; char S[N]; mint frac[N], Inv[N], ifrac[N]; mint f[N][N], g[N][N]; inline mint C(int n, int m) { return frac[n] * ifrac[m] * ifrac[n - m]; } signed main() { scanf("%d%s", &n, S + 1); for (int i = 1; i < n; ++i) g[i][i + 1] = 1; g[n][1] = 1, frac[0] = ifrac[0] = 1; for (int i = 1; i <= n; ++i) { frac[i] = frac[i - 1] * i; Inv[i] = i == 1 ? 1 : 0_mod - (mint::mod / i) * Inv[mint::mod % i]; ifrac[i] = ifrac[i - 1] * Inv[i]; } for (int len = 3; len <= n + 1; ++len) for (int l = 1; l <= n; ++l) { int r = l + len - 1; int rr = r > n ? r - n : r; for (int k = l + 1; k < r; ++k) { int kk = k > n ? k - n : k; mint o = C(r - l - 2, k - l - 1); g[l][rr] += g[l][kk] * g[kk][rr] * o; if (S[l] == 'R') { f[l][rr] += ((k - l) * g[l][kk] * g[kk][rr] + g[l][kk] * f[kk][rr] + g[kk][rr] * f[l][kk]) * o; } if (S[rr] == 'L') { f[l][rr] += ((r - k) * g[l][kk] * g[kk][rr] + g[l][kk] * f[kk][rr] + g[kk][rr] * f[l][kk]) * o; } } g[l][rr] *= (S[l] == 'R') + (S[rr] == 'L'); } mint sum = 0; for (int i = 1; i <= n; ++i) sum += f[i][i]; sum *= ifrac[n]; printf("%d\n", sum.raw()); return 0; }
本文作者:XuYueming,转载请注明原文链接:https://www.cnblogs.com/XuYueming/p/18508808。
若未作特殊说明,本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具