首页 > 其他分享 >AGC041F Histogram Rooks

AGC041F Histogram Rooks

时间:2025-01-08 19:44:28浏览次数:1  
标签:Rooks int AGC041F 钦定 位置 len Histogram include MOD

一个朴素的想法是容斥:考虑钦定 \(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;
}

标签:Rooks,int,AGC041F,钦定,位置,len,Histogram,include,MOD
From: https://www.cnblogs.com/Aria-Math/p/18660412

相关文章

  • AGC026D Histogram Coloring 题解
    [AGC026D]HistogramColoring题解给定\(n\)列的网格,每列高为\(h_i\),将每个格子染色成红色或蓝色,使得每个\(2\times2\)的区域都恰好有两个蓝格子和两个红格子,求方案数(对\(10^9+7\)取模)。\(1\leqn\leq100,1\leqh_i\leq10^9\)性质为了方便讲述,先假设\(h_i=h_{i+......
  • SciTech-Mathematics-Probability+Statistics-Relative Frequency Histogram: Definit
    RelativeFrequencyHistogram:Definition+ExampleBYZACHBOBBITTPOSTEDONFEBRUARY19,2020Ofteninstatisticsyouwillencountertablesthatdisplayinformationaboutfrequencies.Frequenciessimplytellushowmanytimesacertaineventhasoccurred.......
  • 人工智能深度学习系列—深度学习中的边界框回归新贵:GHM(Generalized Histogram Loss)全
    文章目录1.背景介绍2.Loss计算公式3.使用场景4.代码样例5.总结1.背景介绍目标检测作为计算机视觉领域的核心技术之一,其精确度的提升一直是研究者们追求的目标。边界框回归作为目标检测中的关键步骤,其性能直接影响到检测的准确性。本文将详细介绍一种新型的边界......
  • LLM-文心一言:通过 date_histogram 聚合来查询特定时间范围内的每个时间桶的最新记录
    在Elasticsearch(ES)中,如果你想通过date_histogram聚合来查询特定时间范围内的每个时间桶(比如每小时、每天等)的最新记录,你需要结合使用date_histogram聚合和top_hits聚合。date_histogram用于按时间分组数据,而top_hits用于在每个时间桶内选择最新的记录。以下是一个示......
  • AGC041F Histogram Rooks
    考察一个合法的棋盘,有一些列上有车,其他的列没有车。有车的列所有格子都被覆盖,没有车的列上的每个格子都需要被同一行的车覆盖。即考察所有极长的行连续段,如果这个连续段涉及的列里包含没有车的列,那么这个行连续段里必须有车。考虑枚举有车的列的集合\(S\),对于每个行连续段,记它......
  • CF1411C - Peaceful Rooks | 思维
    links在一个\(n\timesn\)的棋盘上有\(m(m<n)\)个棋子。若棋子处于同一行或同一列便认为他们可以互相攻击。初始时棋子之间均不可互相攻击。你可以进行若干次操作,每次操作可以将棋子纵向移动任意格或横向移动任意格,要求移动之后棋子之间不能互相攻击。求使得棋子均处在主......
  • Atcoder Grand Contest 041 F - Histogram Rooks
    考虑容斥。我们钦定一些格子组成的集合不能被覆盖,设为\(A\)。把与\(A\)中的点同行同列的点抠掉,剩余的点则是可放可不放的,总方案数就是\(2^{\text{剩余点的个数}}\),乘以\((-1)^{|A|}\)并求和即可。这个做法直接优化显然不行。我们考虑设\(A\)中的点所在的列组成的不可重集......
  • [AGC041F] Histogram Rooks 题解
    题目链接点击打开链接题目解法好牛(难)的题!!!所有都被覆盖不难想到容斥暴力的容斥是钦定集合\(S\)中的位置都没被覆盖,然后把不能填棋子的点都去掉,假设剩下的不受限制的点的个数为\(c\),则答案为\(\sum2^c(-1)^{|S|}\)这个暴力是很难直接优化的如果一列被有点被钦定了,那么......
  • Prometheus最佳实践 Summary和Histogram
    本文分享自华为云社区《Prometheus最佳实践Summary和Histogram》,作者:张俭。前言Histogram和Summary都是复杂的指标,不仅仅是因为直方图和summary包含了多个时间序列,而且它们还较难使用正确。观测中的Count和SumHisto和summary都是采样观测,典型的采样维度有 响应大小 和 ......
  • 无涯教程-Seaborn - 直方图(Histogram)
    直方图表示数据分布,方法是沿数据范围形成条形图,然后绘制条形图以显示落入每个条形图的观察数。Seaborn附带了一些数据集,在前几章中只使用了很少的数据集。无涯教程已经学习了如何加载数据集以及如何查找可用数据集列表。importpandasaspdimportseabornassbfrommatplot......