Atcoder ABC387F Count Arrays 题解 [ 绿 ] [ 基环树 ] [ 树形 dp ] [ 前缀和优化 ]
Count Arrays:一眼秒的计数题。
思路
显然,把小于等于的条件化为大的向小的连单向边,每个数的入度都是 \(1\),就会形成一个基环树森林。
那么考虑这个环上能填什么数。因为所有数都小于等于他后面的数,所以所有数都只能相等。这就启发我们在基环树上缩点之后再进行计数。
那么当缩完点计数时如何计算呢?有个很简单的 dp,定义 \(dp_{i,j}\) 表示考虑到节点 \(i\),节点 \(i\) 填 \(j\) 的方案数,则很容易能写出转移:
\]
直接转移是 \(O(nm^2)\) 的,前缀和优化即可做到 \(O(nm)\)。
答案计算时将所有基环树的答案乘起来即可。
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi=pair<int,int>;
using pii=pair<int,pi>;
const ll mod=998244353;
int n,m,a[10005];
int dfn[10005],low[10005],stk[10005],cnt=0,tp=0,scc[10005],tot=0;
bitset<10005>instk,vis,rd;
vector<int>g[10005],tr[10005];
ll ans=1,dp[3005][3005],f[3005][3005];
void tarjan(int u)
{
dfn[u]=low[u]=++tot;
instk[u]=1,stk[++tp]=u;
for(auto v:g[u])
{
if(dfn[v]==0)
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instk[v])
{
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u])
{
int now;
cnt++;
do{
now=stk[tp--];
instk[now]=0;
scc[now]=cnt;
}while(now!=u);
}
}
void dfs(int u)
{
for(int i=1;i<=m;i++)dp[u][i]=1;
for(auto v:tr[u])
{
dfs(v);
for(int i=1;i<=m;i++)
{
dp[u][i]=(dp[u][i]*f[v][i])%mod;
}
}
for(int i=1;i<=m;i++)f[u][i]=(f[u][i-1]+dp[u][i])%mod;
}
int main()
{
//freopen("sample.in","r",stdin);
//freopen("sample.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
g[a[i]].pb(i);
}
for(int i=1;i<=n;i++)if(dfn[i]==0)tarjan(i);
for(int i=1;i<=n;i++)
{
int fu=scc[i];
for(auto v:g[i])
{
int fv=scc[v];
if(fu!=fv)
{
tr[fu].pb(fv);
rd[fv]=1;
}
}
}
for(int i=1;i<=cnt;i++)
{
if(rd[i]==0)
{
dfs(i);
ans=(ans*f[i][m])%mod;
}
}
cout<<ans;
return 0;
}
Atcoder ABC387F Count Arrays 题解 [ 绿 ] [ 基环树 ] [ 树形 dp ] [ 前缀和优化 ]的更多相关文章
- 洛谷 P1453 城市环路 ( 基环树树形dp )
题目链接 题目背景 一座城市,往往会被人们划分为几个区域,例如住宅区.商业区.工业区等等.B市就被分为了以下的两个区域--城市中心和城市郊区.在着这两个区域的中间是一条围绕B市的环路,环路之内便是B市 ...
- HDU6403 Card Game【基环树 + 树形DP】
HDU6403 Card Game 题意: 给出\(N\)张卡片,卡片正反两面都有数字,现在要翻转一些卡片使得所有卡片的正面的值各不相同,问最小翻转次数和最小翻转情况下的不同方案数 \(N\le 10 ...
- 骑士 HYSBZ - 1040(基环树+树形dp)
Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境中 ...
- BZOJ 1040 骑士 基环树 树形DP
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1040 题目大意: Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫 ...
- bzoj 1040: [ZJOI2008]骑士【基环树+树形dp】
没考虑可以连着两个不选--直接染色了 实际上是基环森林,对于每棵基环树,dfs找出一个环边,然后断掉这条边,分别对这条边的两端点做一边treedp,取max加进答案里 treedp是设f[u]为选u点 ...
- BZOJ 1040 [ZJOI2008]骑士 (基环树+树形DP)
<题目链接> 题目大意: Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的 ...
- 4.13 省选模拟赛 树 树形dp 卷积 NTT优化dp.
考试的时候 看到概率 看到期望我就怂 推了一波矩阵树推自闭了 发现 边权点权的什么也不是. 想到了树形dp 维护所有边的断开情况 然后发现数联通块的和再k次方过于困难. 这个时候 应该仔细观察一下 和 ...
- BZOJ2878 [Noi2012]迷失游乐园 【基环树 + 树形dp + 期望dp】
题目链接 BZOJ2878 题解 除了实现起来比较长,思维难度还是挺小的 观察数据范围发现环长不超过\(20\),而我们去掉环上任何一个点就可以形成森林 于是乎我们枚举断掉的点,然后只需求出剩余每个点 ...
- day 2 下午 骑士 基环树+树形DP
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #inc ...
- 51nod 1353 树 | 树形DP经典题!
51nod 1353 树 | 树形DP好题! 题面 切断一棵树的任意条边,这棵树会变成一棵森林. 现要求森林中每棵树的节点个数不小于k,求有多少种切法. 数据范围:\(n \le 2000\). 题解 ...
随机推荐
- MySQL之批量更新多条记录不同值
之前文章:https://www.cnblogs.com/xingxia/p/mysql_basic.html mysql更新语句很简单,更新一条数据的某个字段,一般这样写: UPDATE mytab ...
- 如何使用blender生成城市群
在我们做数字孪生相关的项目的时候,会需要生成一些城市的模型,这时候我们可以使用 blender 来生成一些城市的模型. 我们,先来看一下效果. 安装 blender blender 是一个开源的 3D ...
- C# Linq 的三种去重方式(Distinct)
前言 关于C#中默认的Distinct方法在什么情况下才能去重,这个就不用我再多讲,针对集合对象去重默认实现将不再满足,于是乎我们需要自定义实现来解决这个问题,接下来我们详细讲解几种常见去重方案,孰好 ...
- Pro更改启动界面
该方法适用于arcgispro 3.1及以上版本,我目前测试到3.3,是可以的. 使用的是pro产品的启动配置文件,利用其中的SplashScreen实现这一需求. 在bin目录下,新建(或编辑)Ar ...
- less 常用方法
介绍 Less 是 CSS 的预处理语言之一,为 CSS 增添了变量.Mixin.函数等特性,使CSS更易于维护扩展. 嵌套(Nesting) .header { .navgation: { font ...
- NATS: 对象存储
https://natsbyexample.com/examples/os/intro/dotnet2 NATS 中的对象存储能力是在 Stream 之上的一种抽象,它将消息的主题视为类似键值对中的键 ...
- 常用 NoSQL 比较
Q: 请根据 CAP 实现程度,分布式实现方式,数据结构,查询方式,存储引擎等比较 mongodb, redis, cassandra, scylladb, dragonflydb, TiKV, co ...
- 使用 JDK19 虚拟线程实现5百万持久连接
使用Project Loom 虚拟线程实现5M 持久连接| 黑客新闻 记得十几年前 erlang 火的时候,单机 20万连接.100万连接不停刷新,后来 golang 也开始炫耀,抛开连结构化错误处理 ...
- 【MyBatis】学习笔记13:延迟加载(懒加载)
目录 Mybatis13:延迟加载(懒加载) 测试 测试1 测试2 部分特殊情况处理 Mybatis13:延迟加载(懒加载) 延迟加载是分步查询的好处,默认是不开启延迟加载的,要开启需要在核心配置文件 ...
- 详解AQS五:深入理解共享锁CountDownLatch
CountDownLatch是一个常用的共享锁,其功能相当于一个多线程环境下的倒数门闩.CountDownLatch可以指定一个计数值,在并发环境下由线程进行减一操作,当计数值变为0之后,被await ...