热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【洛谷】COCI2008-2009第四轮PERIODNI问题深入解析

题目链接:https://www.luogu.com.cn/problem/P6453在解决COCI2008-2009第四轮PERIODNI问题时,我们需要逐行分析。由于一行中的字符若被断开则不再视为同一行,因此每行的最大矩形区域需要单独计算。通过这种方法,可以确保每层都能找到其最大连续子矩形,从而有效解决问题。

题目链接:https://www.luogu.com.cn/problem/P6453

因为一行中如果断开的话就不算在同一行了,所以我们可以一行一行来考虑。

这样的话每层都会截出来一个最大的矩形,这有点向一个树形结构,可以用笛卡尔树(还是有点难想的)


这里提一下,对于2312131这样的棋盘

三个1本来应该是同等级别的,但是在树上却有父子关系,这不要紧,因为它们之间的高的差为0


记f[i][j]表示以i为代表的区域内放j个棋的方案数,sz[u]表示以u为根的子树大小

显然,对于节点u,其矩阵的长为sz[u],宽为h[u]-h[fa[u]]。

所以我们先跑一个树上背包,合并所有子树的情况,再单独讨论该节点的区域内的放置情况。

假设一共放j个棋,在该区域内放k个棋则方案数为\(\dbinom{sz[u]-j+k}{k} \dbinom{h[u]-h[fa[u]]}{k} k!\)


本来矩阵的长为sz[u],但是要在子节点的范围内先放上j-k个棋,占用了j-k列,故还有sz[u]-j+k列能用来放


#include
using namespace std;
const int N = 505, M = 1e6 + 5, P = 1e9 + 7;
int n, m, top, stk[N], inv[M], invfac[M], fac[M];
int h[N], f[N][N], sz[N], son[N][2];
inline void init(int n){
inv[1] = fac[1] = fac[0] = invfac[1] = invfac[0] = 1;
for (int i = 2; i <= n; ++i){
inv[i] = 1ll * (P - P / i) * inv[P % i] % P;
invfac[i] = 1ll * invfac[i - 1] * inv[i] % P;
fac[i] = 1ll * fac[i - 1] * i % P;
}
}
inline int C(int x, int y){
if (x <0 || y <0 || x > y) return 0;
return 1ll * fac[y] * invfac[y - x] % P * invfac[x] % P;
}
void dfs(int u, int fath){
f[u][0] = 1, sz[u] = 1;
int hi = h[u] - h[fath];
for (int i = 0; i <= 1; ++i){
int v = son[u][i];
if (!v) continue;
dfs(v, u);
for (int j = min(sz[u], m); j >= 0; --j)
for (int k = 1; k <= min(sz[v], m - j); ++k)
f[u][j + k] = (f[u][j + k] + 1ll * f[u][j] * f[v][k]) % P;
sz[u] += sz[v];
}
for (int i = min(sz[u], m); i >= 1; --i)
for (int j = 1; j <= min(i, hi); ++j)
f[u][i] = (f[u][i] + 1ll * f[u][i - j] * C(j, sz[u] - i + j) % P * C(j, hi) % P * fac[j]) % P;
}
int main(){
init(M - 5);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i)
scanf("%d", h + i);
for (int i = 1; i <= n; ++i){
while (top && h[i] if (top) son[stk[top]][1] = i;
stk[++top] = i;
}
dfs(stk[1], 0);
printf("%d\n", f[stk[1]][m]);
return 0;
}


推荐阅读
  • 本文介绍了一个使用Keras框架构建的卷积神经网络(CNN)实例,主要利用了Keras提供的MNIST数据集以及相关的层,如Dense、Dropout、Activation等,构建了一个具有两层卷积和两层全连接层的CNN模型。 ... [详细]
  • 本文探讨了在Java应用中,由于对象间循环引用导致重写toString方法时出现StackOverflowError的具体情况,并提供了有效的解决方案。 ... [详细]
  • 本文详细介绍了C++标准模板库(STL)中各容器的功能特性,并深入探讨了不同容器操作函数的异常安全性。 ... [详细]
  • 首先说一下,这是我在CSDN上的第一个文章,其实这个账号早在几年前就申请了,不过当时只是为了下载一个资源,而且也不怎么懂信息技术相关的领域,后来就再也没怎么动过,直到今天我才开始使用这个账号 ... [详细]
  • 学习目的:1.了解android线程的使用2.了解主线程与子线程区别3.解析异步处理机制主线程与子线程:所谓主线程,在Windows窗体应用程序中一般指UI线程,这个是程序启动的时 ... [详细]
  • Flutter入门指南:实现自动关闭的对话框与提示
    本文为Flutter系列教程的一部分,专注于讲解如何在Flutter应用中实现自动关闭的对话框和提示。通过具体的代码示例,帮助开发者掌握SnackBar、BottomSheet和Dialog的使用方法。 ... [详细]
  • 使用Python轻松合并大量复杂Excel文件
    当面对大量的Excel文件时,如何高效地将它们合并成一个文件成为了一项挑战。本文将指导初学者如何利用Python的几个库,在几十行代码内完成这一任务。 ... [详细]
  • 本文深入探讨了企业级开发框架NHibernate和Spring.NET的关键特性之一——面向方面编程(AOP)。文章不仅介绍了AOP的基本概念及其如何增强面向对象编程(OOP),还详细说明了Spring.NET中AOP的具体应用,包括事务管理和自定义方面的实现。 ... [详细]
  • 今天我在操作Git时遇到了一个问题,即我的仓库进入了分离的HEAD状态,这与之前讨论过的‘即使本地有更改,git push仍显示所有内容最新’的问题类似。 ... [详细]
  • UnityNGUIScrollView苹果式滑动
    又回来写博客了,这回已经开始上班了,所以就发一发工作中解决的难题吧。单个展示Panel(苹果式)以前对UI的滑动组件很烦心,不是很会用,这回项目要求写一个类似于苹果的文件滑动效果, ... [详细]
  • 导读上一篇讲了zsh的常用字符串操作,这篇开始讲更为琐碎的转义字符和格式化输出相关内容。包括转义字符、引号、print、printf的使用等等。其中很多内容没有必要记忆,作为手册参 ... [详细]
  • 本文详细介绍了 C# 编程语言中 Main 方法的作用、不同形式及其使用场景,帮助开发者更好地理解和应用这一重要概念。 ... [详细]
  • AIY计划由Google发起,旨在通过提供易于使用的工具包和技术支持,激发全球创客的创造力,推动人工智能技术的普及与创新。 ... [详细]
  • CyclicBarrier是一种同步辅助类,能够在多个线程到达某个屏障点时进行阻塞,直到所有参与的线程都达到这一屏障点后,所有线程才继续执行。本文将详细介绍CyclicBarrier的工作原理及应用场景。 ... [详细]
  • 探索Arjun v1.3:高效挖掘HTTP参数的利器
    本文将详细介绍一款名为Arjun的开源安全工具,该工具能够帮助安全研究人员有效提取和分析HTTP参数。请注意,Arjun v1.3要求运行环境为Python 3.4及以上版本。 ... [详细]
author-avatar
风流逍遥快活_936
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有