AGC041F Histogram Rooks

news/2025/1/8 19:33:09/文章来源:https://www.cnblogs.com/Aria-Math/p/18660412

一个朴素的想法是容斥:考虑钦定 \(S\) 集合的位置没有被车覆盖,则答案是 \((-1)^{|S|}2^{c}\),其中 \(c\) 是可以放车的位置,可以直接 dp 做到 \(\mathrm{O}(2^n \text{poly}(n))\),但是难以优化。

延续容斥的想法,注意到钦定一个位置后会直接 ban 掉整列,我们设 \(f(S)\) 表示所有钦定的位置所在列的集合恰好为 \(S\) 的答案,则答案为 \(\sum f(S)\)。考虑二次容斥,钦定 \(T \subseteq S\) 所在列并没有实际钦定位置,则 \(f(S) = \sum (-1)^{|T|}g(T)\)


如图,把棋盘拆成若干极长段,注意到每段的贡献可以分开计算:假设当前段的长度为 \(len\),有 \(p\) 个位置在 \(S\) 中,有 \(q\) 个位置同时在 \(T\) 中,则贡献为:

  • 当前极长段没有钦定位置,贡献为 \(2 ^ {len - p}\)
  • 当前极长段钦定了至少一个位置,贡献为 \(\sum\limits_{i=1}^{p-q}(-1)^i\binom{p-q}{i} = -[p \neq q]\)

假设当前段高为 \(h\),则总贡献是 \((2^{len-p}-[p \neq q])^h\)

考虑对极长段建类似笛卡尔树状物,但是这里是多叉的。在决策到 \(u\) 时,子树所在列是否加入 \(S\) 和加入 \(T\) 都已决定了,只需考虑当前高度的列的决策即可。设 \(f(u, i, 0/1)\) 表示子树内有 \(i\) 列在 \(S\) 中,当前 \(p\) 是否等于 \(q\),转移是做树形背包,最后在加入当前连续段的贡献即可。时间复杂度 \(\mathrm{O}(n^2)\)

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
using ll = long long;
const int N = 410;
const int MOD = 998244353;
int n, h[N], len[N], more[N], a[N];
ll f[N][N][2], g[N][2], b[N];
vector<int> G[N];
void Add(ll &x, ll y) {x += y; if(x >= MOD) x -= MOD;
}
int Build(int l, int r, int fat) {if(l == r) return len[l] = more[l] = 1, a[l] = h[l] - h[fat], l;int u = min_element(h + l, h + r + 1) - h;len[u] = r - l + 1, a[u] = h[u] - h[fat];int lst = l - 1;for(int i = l; i <= r; ++i) if(h[i] == h[u]) {if(lst != i - 1) G[u].push_back(Build(lst + 1, i - 1, u));lst = i, ++more[u];}if(lst != r) G[u].push_back(Build(lst + 1, r, u));return u;
}
ll Pow(ll a, int p = MOD - 2) {ll ans = 1;for(; p; p >>= 1, a = a * a % MOD)if(p & 1) ans = ans * a % MOD;return ans;
}
void Dfs(int u) {f[u][0][0] = 1;for(int i = 1; i <= more[u]; ++i) {for(int p = 0; p <= i; ++p) g[p][0] = g[p][1] = 0;for(int p = 0; p < i; ++p)for(int j : {0, 1}) if(f[u][p][j]) {Add(g[p][j], f[u][p][j]);Add(g[p + 1][1], f[u][p][j]);Add(g[p + 1][j], MOD - f[u][p][j]);}for(int p = 0; p <= i; ++p) f[u][p][0] = g[p][0], f[u][p][1] = g[p][1];}int now = more[u];for(int v : G[u]) {Dfs(v);for(int p = 0; p <= now + len[v]; ++p) g[p][0] = g[p][1] = 0;for(int p = 0; p <= now; ++p)for(int q = 0; q <= len[v]; ++q)for(int i : {0, 1}) for(int j : {0, 1}) Add(g[p + q][i | j], f[u][p][i] * f[v][q][j] % MOD);now += len[v];for(int p = 0; p <= now; ++p)f[u][p][0] = g[p][0], f[u][p][1] = g[p][1];}for(int p = 0; p <= len[u]; ++p) for(int i : {0, 1}) if(f[u][p][i]) {ll val = Pow(b[len[u] - p] + MOD - i, a[u]);f[u][p][i] = f[u][p][i] * val % MOD;}
}
int main() {//freopen("data.in", "r", stdin);//freopen("code.out", "w", stdout);cin.tie(0)->sync_with_stdio(0);cin >> n;for(int i = 1; i <= n; ++i) cin >> h[i];b[0] = 1;for(int i = 1; i <= n; ++i) b[i] = b[i - 1] * 2 % MOD;int rt = Build(1, n, 0);Dfs(rt);ll ans = 0;for(int p = 0; p <= len[rt]; ++p)for(int i : {0, 1}) if(f[rt][p][i])Add(ans, f[rt][p][i]);printf("%lld\n", ans);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/866031.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rust学习十六.1、并发-乱弹和一个简单并发例子

如书本作者所言,并发编程在绝大部分语言中,都是相对复杂和困难的。 所以,涉及的内容会相对多一些,所涵盖的内容绝对不是几篇文章所可以容纳的。 权当一个乱弹琴! 和此系列的其它文章一样,本文的内容绝大部分来自于相关书籍,本人做了一些摘裁的工作,取我所需!一、无畏并…

解决jenkins git 拉取代码超时问题

jenkins默认的是时间是10分钟,在git fetch时候超过10分钟了就报错失败了,可在项目源码管理 新增 advance clone behaviours

Java Bluetooth 蓝牙通讯 BlueCove 扫描附近的蓝牙设备

目录BlueCove项目概述BlueCove API架构API的设计原则和实现方式关键类和方法的功能描述测试代码获取本机(PC)蓝牙扫描蓝牙 BlueCove项目概述 BlueCove是一个开源的蓝牙协议栈实现,旨在为Java开发者提供一个全面的、易于使用的API,从而在应用程序中实现蓝牙功能。该项目支持多…

英伟达世界基础模型 Cosmos,教 AI 理解物理世界;阿里通义与雷鸟合作推出 AI 眼镜丨 RTE 开发者日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的新闻」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文章 」、「有看点的 会议 」,但内容仅代表编辑的…

.NET 窗口置于最顶层

本文介绍如何将窗口置于最顶层,以及解决在顶层显示时对锁屏登录界面的影响。用于实现类似Launcher、系统工具等应用需要窗口层级比Windows开始菜单以及置顶任务栏还要高的场景 一般情况下的窗口置顶,可以设置WPF窗口属性Topmost=true 也可以使用WIN32-SetWindowPos函数SetWin…

汽修行业的智能化转型:AI赋能员工培训SOP策略

随着智能化技术的飞速发展,汽修行业也迎来了前所未有的变革机遇。在这一背景下,如何构建高效、标准化的员工培训SOP(Standard Operating Procedure)策略,成为汽修企业提升竞争力、实现智能化转型的关键。本文将探讨智能AI在汽修行业员工培训SOP策略构建中的应用,特别是提…

智慧医疗新纪元:帮助中心引领的智能化转型之路

在科技日新月异的今天,智慧医疗已经成为医疗领域发展的重要趋势。智慧医疗不仅意味着医疗设备的智能化,更代表着整个医疗服务流程的数字化转型。在这一变革过程中,如何有效利用帮助中心驱动医疗机构的转型与升级,成为了一个值得深入探讨的课题。本文将探讨智慧医疗的智能跃…

sqlalchemy.exc.OperationalError

最后发现是 密码中含特殊字符@导致的连接报错其他参考: sqlalchemy.exc.OperationalError通常指示Python应用程序与数据库之间的连接出现问题。这里有一些可能的原因和解决方案:数据库连接参数错误:检查你的数据库连接字符串(DSN)。确保主机名、端口、数据库名称、用户名和…

五大优势:开源AI视频监控助力精准打击公租房非法倒卖行为

一. 用户痛点:传统监控面临的挑战与隐患 公租房作为社会保障性住房的一种,旨在为低收入群体提供基本的居住保障。然而,随着市场上房地产倒卖行为的增多,许多公租房被非法转租或倒卖给非资格居民,导致公租房资源流失、社会公平受损。政府在这方面的监管面临诸多困难,传统的…

Omnivore 替代品 Readeck 安装与使用教程

前段时间 Omnivore 宣布服务关停,作为一个长期使用 Omnivore 的用户,我需要寻找替代方案。 我对替代品的核心需求是:浏览器插件:支持一键剪藏当前网页。 RSS 支持:能够输入 RSS 地址并定时抓取更新。 API 接口:可以通过 API 与我的 logseq 进行集成。寻找替代品的过程: …

前端之canvas实现电子签约完成线上签署功能

电子签名,下载带有签名的合同png/pdf格式,前端/vue实现电子签功能。最近发现现在租房还是签合同,越来越多采用电子签约的方式进行,好处不用多说节约成本,节约时间。抱着好奇的心理,尝试自己动手实现一个电子签。原来并不复杂主要通过了canvas绘画能力进行实现的。最近发现…

git怎么玩

首先如果是windos下个git bash 1.自己用git,用于本地和github的交互!