乘法原理,加法原理,多重集的排列数(多个系列操作穿插的排列数) 进阶指南 洛谷p4778
https://www.luogu.org/problemnew/solution/P4778
非常好的题目,囊括了乘法加法原理和多重集合排列,虽然最后使用一个结论解出来的。。
给定一个n的排列,用最少的次数将排列变成单调递增
请问这样的操作有多少种
套路:位置i向位置p[i]连单向边,最后会形成l个环
先来考虑单个环:
引理:将长度为len的环拆成len个自环至少操作len-1次
套路:
一个数对应有且仅有一个位置,且一个位置有且仅有一个数
这就意味着整个图上每个点入度出度都为1
也就意味着图上的环都是简单环
于是DFS找环并统计长度可以用很简单的代码实现
每次交换操作实际上是交换边,在单向边组成的环中交换任意两条边后必定形成两个独立的环
即每次交换操作会将len的环拆成长度为x,y的两环
那么考虑有多少种拆法T(x,y)=(x==y?x:x+y)种拆分方式
设F[len]为将长度len的环拆成len个自环的操作方法数
显然有F[len]=sum{先拆成(i,len-i)的方法数}
那么先拆成(i,len-i)的方法数=T(i,len-i)*F[i]*F[len-i]*step(i,len-i)
由于把长为i的环拆成自环要i-1步,长len-i的环拆成自环要len-i-1步,这些步数可以先后穿插,但是一个环集合内自己的步数本可以打乱,所以等价于可重集合的排列数
由多重集的排列数,总共有step(i,len-i)=(len-2)!/(i-1)!*(len-i-1)! 种步数
所以最后一个长为len的环的公式是
F[len]=sum:T(i,len-i)*F[i]*F[len-i]*(len-2)!/(i-1)!*(len-i-1)!
所以最终答案是所有环相乘 ,再乘可重集合的排列数,即环于环相乘时步数也是可以先后穿插的!
事实上,有F[len]=len^(len-2)的结论
最新文章
- linux常用命名复习
- 开启ACM的征途
- twisted 安装时,安装顺序为 zope.interface ->;twisted
- UVa 10256 凸包简单应用
- Java调度框架Quartz简单示例
- JAVA经典算法40题
- VMware虚拟机安装教程
- 设计模式之迭代器模式——Java语言描述
- week7 ls
- [转]Oracle left join \ right join
- Oracle字符串函数
- Gold Rush(hnu13249)
- MySQL更改了my.ini的#Path to the database root后,数据还写到原来的文件夹
- Qt通过ODBC来操作Excel
- appium安装与部署
- Use a TL431 shunt regulator to limit high ac input voltage
- 浅谈https\ssl\数字证书
- nyoj 456——邮票分你一半——————【背包思想搜索】
- BZOJ2877 [Noi2012]魔幻棋盘
- iOS编程规范(整理)
热门文章
- (6)Java数据结构-- 转:JAVA常用数据结构及原理分析
- Centos7配置静态IP后无法ping通外部网络的问题(无法上网)
- protobuf 安装与卸载
- 论文笔记:Joint Embeddings of Shapes and Images via CNN Image Purification
- python3之模块SMTP协议客户端与email邮件MIME对象
- VS2013中如何解决error C4996: 'fopen'问题
- 设置Vmware中Kali_linux 共享文件夹
- MVC之基架
- java泛型类型变量能调用的方法
- Ex4_21 最短路径算法可以应用于货币交易领域..._第十二次作业