「UER#2」信息的交换

吉利题..

不难发现,置换中的每一个循环是独立的,每一个循环分别对应一个独立的联通块。

根据题目的性质,每一个联通块做的事情等价于其按照编号从小到大遍历的的dfs生成树做的事情,那么只需要考虑一棵dfs生成树做的事情即可。

对于一棵dfs生成树,将每个点的儿子按照编号从小到大排序,考虑节点 \(u\) 以及它的儿子 \(v_1,v_2..v_k\) ,其中 \(v_k\) 的权值最终会到 \(u\) 的位置上,\(\forall i<k,v_i\) 的值会先到 \(v_{i+1}\) 的位置上去,到访问到 \(v_i+1\) 的时候在继续做同样的事情,最终会到达 \(v_{i+1}\) 这棵子树最左边的叶子上。定义逆dfs序为先遍历编号大的儿子的dfs序,这个过程做完相当于节点 \(v\) 到了逆dfs序的前一位对应的节点上,根节点到逆dfs序上最后一位对应的节点。相当于按照逆dfs序做了一个置换!

那么只需要将每个循环对应的逆dfs序求出来,再计算有多少棵树的逆dfs序符合。对于一棵符合的树,其连上一些返祖边可以得到符合的图,大力DP一下即可,复杂度 \(\mathcal O(n^3)\) 。

code

/*program by mangoyang*/
#include <bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = 505, mod = 998244353;
int vis[N], pw[N], a[N], f[N][N], h[N][N], c[N][N], n;
inline void up(int &x, int y){ x = x + y >= mod ? x + y - mod : x + y; }
inline int gao(vector<int> &A){
if(!(int) A.size()) return 1;
int m = A.size();
for(int i = 0; i < m; i++)
for(int j = i + 1; j < m; j++)
c[i][j] = c[i][j-1] + (A[j] > A[i]);
for(int i = 0; i < m; i++)
for(int j = 0; j < m; j++) f[i][j] = 0;
for(int i = 0; i < m; i++) f[i][i] = h[i][i] = 1;
for(int i = m - 1; ~i; i--)
for(int j = i + 1; j < m; j++){
f[i][j] = h[i][j] = 1ll * f[i+1][j] * pw[c[i][j]] % mod;
for(int k = i; k < j; k++) if(A[i] > A[k+1])
up(f[i][j], 1ll * h[i][k] * f[k+1][j] % mod);
}
return f[0][m-1];
}
int main(){
read(n), pw[0] = 1;
for(int i = 1; i <= n; i++) read(a[i]);
for(int i = 1; i <= n; i++) pw[i] = 2ll * pw[i-1] % mod;
int ans = 1;
for(int i = 1; i <= n; i++) if(!vis[i]){
vector<int> A;
vis[i] = 1;
for(int p = a[i]; p != i; p = a[p])
A.push_back(p), vis[p] = 1;
ans = 1ll * ans * gao(A) % mod;
}
cout << ans << endl;
}

「UER#2」信息的交换的更多相关文章

  1. 「UER#2」谣言的传播

    「UER#2」谣言的传播 写了个乱搞,怎么莫名其妙就AC了,这...,之后又想了30min结合题解终于会证了. 首先最大值比较简单,记 \(f_i\) 为第 \(i\) 个点能到达的点数,上界 \(\ ...

  2. Diary / Solution Set -「WC 2022」线上冬眠做噩梦

      大概只有比较有意思又不过分超出能力范围的题叭.   可是兔子的"能力范围" \(=\varnothing\) qwq. 「CF 1267G」Game Relics   任意一个 ...

  3. 图解最长回文子串「Manacher 算法」,基础思路感性上的解析

    问题描述: 给你一个字符串 s,找到 s 中最长的回文子串. 链接:https://leetcode-cn.com/problems/longest-palindromic-substring 「Ma ...

  4. 「Android 开发」入门笔记

    「Android 开发」入门笔记(界面编程篇) ------每日摘要------ DAY-1: 学习笔记: Android应用结构分析 界面编程与视图(View)组件 布局管理器 问题整理: Andr ...

  5. 「POJ 3666」Making the Grade 题解(两种做法)

    0前言 感谢yxy童鞋的dp及暴力做法! 1 算法标签 优先队列.dp动态规划+滚动数组优化 2 题目难度 提高/提高+ CF rating:2300 3 题面 「POJ 3666」Making th ...

  6. 「C语言」文件的概念与简单数据流的读写函数

    写完「C语言」单链表/双向链表的建立/遍历/插入/删除 后,如何将内存中的链表信息及时的保存到文件中,又能够及时的从文件中读取出来进行处理,便需要用到”文件“的相关知识点进行文件的输入.输出. 其实, ...

  7. 「C语言」Windows+EclipseCDT下的C语言开发环境准备

    之前写过一篇 「C语言」在Windows平台搭建C语言开发环境的多种方式 ,讨论了如何在Windows下用DEV C++.EclipseCDT.VisualStudio.Sublime Test.Cl ...

  8. 日均百万 PV 的站点如何做性能监测?试试「3M口罩」!

    对很多开发者而言,如果网站的日流量达到百万级别,峰值 PV 也突破了 3 万,这样的站点在线下测试的时候总是让人心力交瘁.... 生产环境下的性能监测问题更是尤其让人头疼! 开发同学在想,运维人员也在 ...

  9. 微服务架构之「 API网关 」

    在微服务架构的系列文章中,前面已经通过文章<架构设计之「服务注册 」>介绍过了服务注册的原理和应用,今天这篇文章我们来聊一聊「 API网关 」. 「 API网关 」是任何微服务架构的重要组 ...

随机推荐

  1. 04-树6 Complete Binary Search Tree (30 分)

    A Binary Search Tree (BST) is recursively defined as a binary tree which has the following propertie ...

  2. Shell字符串截取(非常详细)

    假设有变量 var=http://www.aaa.com/123.htm. 1. # 号截取,删除左边字符,保留右边字符. 1 echo ${var#*//} 其中 var 是变量名,# 号是运算符, ...

  3. 使用helm进行kubernetes包管理

    1. 安装helm package https://github.com/helm/helm/blob/master/LICENSE 2. 将 helm 配置到环境变量 3. 使用helm的前提是安装 ...

  4. GlusterFS 安装

    一.简介 GlusterFS 是近年兴起的一个高性能开源分布式文件系统,其目标是全局命名空间.分布式前端的高性能文件系统,目前已被 RedHat 看中,GlusterFS 具有高扩展.高可性.高性能. ...

  5. java判断指定路径文件夹是否存在,若不存在则创建新的文件夹

    File file = new File(dirPath); if (!file.exists()) { file.mkdirs(); }

  6. Oracle 日期各个部分常用写法

    --1.日期的各部分的常用的的写法 --- --1) 取时间点的年份的写法: SELECT TO_CHAR(SYSDATE,'YYYY') FROM DUAL; --结果:2019 --2) 取时间点 ...

  7. cannot connect to daemon at tcp:5037: cannot connect to 127.0.0.1:5037: 由于目标计算机积极拒绝,无法连接。 (10061)

    原因是:5037端口被占用 解决方法:1.查找5037被谁占用   netstat -ano | findstr "3037" 2.查看对应的是哪个任务  tasklist | f ...

  8. 什么是依赖注入 IoC

    设计原则:依赖注入原则 依赖倒置原则,是一种程序设计模式的原则 高层模块不应该依赖底层模块,二者都应该依赖其抽象. 抽象不应该依赖细节,细节应该依赖抽象.依赖导致原则很好的体现了“面向接口编程”的思想 ...

  9. mark_Linux_wc

    Linux wc命令 Linux wc命令用于计算字数. 利用wc指令我们可以计算文件的Byte数.字数.或是列数,若不指定文件名称.或是所给予的文件名为"-",则wc指令会从标准 ...

  10. matlab学习笔记13_1 函数返回值

    一起来学matlab-matlab学习笔记13函数 13_1 函数返回值 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 https://blog.csdn.net/qq_36556 ...