洛谷P2606 [ZJOI2010]排列计数 组合数学+DP
题意:称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很大,只能输出模P以后的值。
解法:我们仔细观察这个pi>=pi/2,想到什么了?像不像二叉树中每个点i和它的两个儿子的编号2i和2i+1。
那么我们可以想象每个点i想它的两个儿子2i/2i+1连边,加上Pi>Pi/2这个条件,那么这棵二叉树就是一棵小根堆。那么我们考虑用dp解决这道题,
设dp[i]表示i个不同的数组成一棵大小为i的小根堆的方案数,状态转移方程为dp[i]=C(i-1,l[i]) * dp[l[i]] * dp[r[i]] ;解释一下:这里的l[i]/r[i]代表大小为i的完全二叉树(为什么要是完全的?因为题目要求的序号是连续的)的左/右子树大小。这个方程的意思是从i-1个数里面选择l[i]个数作为左子树方案数乘以剩下r[i]个数作为右子树方案数。
那么我们预处理l[i]/r[i]就可以计算答案了。
注意此题p有可能>=n,所以要用Lucas定理计算组合数。
- #include<bits/stdc++.h>
- using namespace std;
- typedef long long LL;
- const int N=1e6+;
- int n,P,l[N],r[N],dp[N];
- int power(int x,int p) {
- int ret=;
- for (;p;p>>=) {
- if (p&) ret=(LL)ret*x%P;
- x=(LL)x*x%P;
- }
- return ret;
- }
- int fac[N],inv[N];
- void prework(int n) {
- fac[]=; inv[]=;
- for (int i=;i<=n;i++) {
- fac[i]=(LL)i*fac[i-]%P;
- inv[i]=power(fac[i],P-);
- }
- l[]=;
- for(int i=,g=;i<=n;g<<=,i+=g) {
- for(int j=;j<=g;j++) l[i+j-]=l[i+j-]+;
- for(int j=;j<=g;j++) l[i+g+j-]=l[i+g+j-];
- }
- for (int i=;i<=n;i++) r[i]=i--l[i];
- }
- int C(int n,int m) {
- if (n>=P || m>=P) return (LL)C(n/P,m/P)*C(n%P,m%P)%P;
- else return (LL)fac[n]*inv[m]%P*inv[n-m]%P;
- }
- int main()
- {
- cin>>n>>P;
- prework(n);
- dp[]=dp[]=;
- for (int i=;i<=n;i++)
- dp[i]=(LL)C(i-,l[i])*dp[l[i]]%P*dp[r[i]]%P;
- cout<<dp[n]<<endl;
- return ;
- }
洛谷P2606 [ZJOI2010]排列计数 组合数学+DP的更多相关文章
- 洛谷P2606 [ZJOI2010]排列计数(组合数 dp)
题意 题目链接 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案 ...
- 洛谷 P2606 [ZJOI2010]排列计数 解题报告
P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...
- ●洛谷P2606 [ZJOI2010]排列计数
题链: https://www.luogu.org/problemnew/show/P2606题解: 组合数(DP),Lucas定理 首先应该容易看出,这个排列其实是一个小顶堆. 然后我们可以考虑dp ...
- 洛谷P2606 [ZJOI2010]排列计数(数位dp)
题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很 ...
- 洛谷P2606 [ZJOI2010]排列计数
题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很 ...
- 洛谷P4071 [SDOI2016] 排列计数 [组合数学]
题目传送门 排列计数 题目描述 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m ...
- 洛谷P2602 [ZJOI2010]数字计数(数位dp)
数字计数 题目传送门 解题思路 用\(dp[i][j][k]\)来表示长度为\(i\)且以\(j\)为开头的数里\(k\)出现的次数. 则转移方程式为:\(dp[i][j][k] += \sum_{t ...
- P2606 [ZJOI2010]排列计数
P2606 [ZJOI2010]排列计数 因为每个结点至多有一个前驱,所以我们可以发现这是一个二叉树.现在我们要求的就是以1为根的二叉树中,有多少种情况,满足小根堆的性质. 设\(f(i)\)表示以\ ...
- 洛谷P2602 [ZJOI2010]数字计数 题解 数位DP
题目链接:https://www.luogu.com.cn/problem/P2602 题目大意: 计算区间 \([L,R]\) 范围内 \(0 \sim 9\) 各出现了多少次? 解题思路: 使用 ...
随机推荐
- pytho 解析fiddler 导出的har文件代码,自动录入api
参考:https://testerhome.com/topics/5276 har导出格式如下: { 'log': { 'pages': [], 'comment': 'exported @ 2019 ...
- [BZOJ4817][SDOI2017]树点涂色:Link-Cut Tree+线段树
分析 与[BZOJ3779]重组病毒唯一的区别是多了一个链上求实链段数的操作. 因为每条实链的颜色必然不相同且一条实链上不会有两个深度相同的点(好像算法的正确性和第二个条件没什么关系,算了算了),画图 ...
- 【30分钟学完】canvas动画|游戏基础(1):理论先行
前言 本文虽说是基础教程,但这是相对动画/游戏领域来说,在前端领域算是中级教程了,不适合前端小白或萌新.阅读前请确保自己对前端三大件(JavaScript+CSS+HTML)的基础已经十分熟悉,而且有 ...
- Memcache和Redis复习总结
Memcache Memcache是一个高性能的分布式的内存对象缓存系统,主要是用来缓存从MySQL数据库中查询的数据,减少对mysql数据库的压力. Memcache的工作流程: 当用户发生一个动态 ...
- Maven的一些常用命令
将本项目的源码部署到本地仓库 mvn clean source:jar install 将本地jar包部署到本地仓库,首先将jar包放在当前目录下,然后执行,这样做比直接把jar包copy到本地仓库更 ...
- 并发测试JMeter及发送Json请求
1.下载 提前安装好jdk1.8 官网下载地址:http://jmeter.apache.org/download_jmeter.cgi 2.解压,双击bin/jmeter.bat 3.jmeter配 ...
- 测开之路一百零五:bootstrap的两种引用方式
一:下载到本地引用: 3.3.7版本:https://getbootstrap.com/docs/3.3/getting-started/#download 下载后解压到本地项目中引用 第二种,cdn ...
- JDK+Tomcat+Eclipse环境搭建过程记录
这学期选了一门公选课叫网络开发工具与技术,主要学习用JSP语言构建网站.在配置环境的过程中遇到不少的坑,于是记录下来,希望能帮到大家. 系统环境:Win10 JDK版本:8u121, JAVA版本1. ...
- Java 与 C++ 的比较
参考 Java 中,一切皆是类 Java 中,所有数据或方法都要放在类中.如果想获得与全局函数等价的功能,可将static方法和static数据放在类里.而 C++ 中有 struct 结构.enum ...
- Pycharm中使用virtualenv创建虚拟环境
虚拟环境是Python解释器的一个私有副本,在这个环境中你可以安装私有包,而且不会影响系统中安装的全局Python解释器. 虚拟环境非常有用,可以在系统的Python解释器中避免包的混乱和版本的冲突. ...