「CF1437F」Emotional Fishermen 题解

小水题一道

1|0Description

有 n(n5000) 个渔民,每个渔民钓了一条重 ai 的鱼,渔民按任意顺序展示他们的鱼。
若当前渔民的鱼的重量为x,之前展示过的鱼的最大重量 y
一个排列满足条件当且仅当对于每个 x,满足 2yx2xy
问有多少个排列满足条件,对 998244353 取模。

2|0Solution

我们如果将每一个曾作为最大重量的鱼看作关键点,那么对于某一种关键点取法,向里面填数是容易计数的。只需要考虑怎样定义状态方便转移即可。
首先,我们将鱼的重量排序,然后定义 dpi 表示第 i 条鱼关键点的方案数。显然有初值 dpn=1。又定义 pi 表示最大的满足 2aipi>ai 的数,则有以下转移:

dpi=aj2aidpj×k=1pj(nj1+k)×k=pj+1ji+1(nj+k)

最后同理处理答案即可。

3|0Code

#include <bits/stdc++.h> using namespace std; using ci = const int; using u32 = uint32_t; using i64 = int64_t; using u64 = uint64_t; template<class T> inline void Max(T &x, const T &y) { if (x < y) x = y; } template<class T> inline void Min(T &x, const T &y) { if (y < x) x = y; } const int N = 5005; const int mod = 998244353; constexpr int dil(int x) { return x >> 31 ? x + mod : x; } struct Module { using cm = const Module; int v; Module() {} Module(int _v) : v(_v) {} #define _(s) friend Module operator s(cm &x, cm &y) _(+) { return dil(x.v + y.v - mod); } _(-) { return dil(x.v - y.v); } _(*) { return u64(x.v) * y.v % mod; } #undef _ #define _(s) void operator s##=(cm &o) { *this = *this s o; } _(+) _(-) _(*) #undef _ }; Module qpow(Module x, int y) { Module z(1); do if (y & 1) z *= x; while (x *= x, y >>= 1); return z; } int n, a[N]; Module dp[N], fct[N], ifct[N]; void init(ci n) { fct[0] = 1; for (int i = 1; i <= n; ++i) fct[i] = fct[i - 1] * i; ifct[n] = qpow(fct[n], mod - 2); for (int i = n; i; --i) ifct[i - 1] = ifct[i] * i; } inline Module mul(int l, int r) { if (!l) return (r == -1); return fct[r] * ifct[l - 1]; } int P[N]; int main() { #ifndef ONLINE_JUDGE freopen(".in", "r", stdin); freopen(".out", "w", stdout); #endif ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n; init(n); for (int i = 1; i <= n; ++i) cin >> a[i]; sort(a + 1, a + 1 + n); for (int i = 1; i <= n; ++i) { int &p = P[i]; while (2 * a[i - p] > a[i]) ++p; --p; } dp[n] = 1; for (int i = n - 1; i; --i) { for (int j = i + 1; j <= n; ++j) { if (a[j] >= 2 * a[i]) { int p = P[j]; dp[i] += dp[j] * mul(n - j, n - j + p - 1) * mul(n - j + p + 1, n - i - 1); } } } Module ans(0); for (int i = 1; i <= n; ++i) { int p = P[i]; ans += dp[i] * mul(n - i, n - i - 1 + p) * mul(n - i + p + 1, n - 1); } cout << ans.v; return 0; }

__EOF__

本文作者TrueFalse
本文链接https://www.cnblogs.com/cqbzljh/p/18686174.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   cqbzljh  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2024-01-22 Johnson 全源最短路算法
点击右上角即可分享
微信分享提示