洛谷P2606 [ZJOI2010]排列计数(数位dp)
题目描述
称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很大,只能输出模P以后的值
输入输出格式
输入格式:
输入文件的第一行包含两个整数 n和p,含义如上所述。
输出格式:
输出文件中仅包含一个整数,表示计算1,2,⋯, ���的排列中, Magic排列的个数模 p的值。
输入输出样例
说明
100%的数据中,1 ≤N ≤ 10^6, P≤ 10^9,p是一个质数。
题解
数位dp?这怕不是个树位dp……
我们把原序列看成一棵二叉树
那么就是要我们求大小为$n$的小根堆有多少个(就是父节点比左右儿子都小)
那么考虑dp,设$dp[i]$表示有多少个大小为$i$的小根堆,$val[i]$表示$i$的子树的大小
因为父亲必须小于儿子,所以根节点只能是最小的点,那么剩下的$i-1$个点里有$val[l]$个可以放在左子树,剩下的都可以放在右子树,方案数为$C_{i-1}^{val[l]}$
然后因为选不同的点之后还能有不同的方案,所以还要乘上方案数
所以最后的状态转移方程是这样的$dp[i]=C_{i-1}^{val[l]}*dp[val[l]]*dp[val[r]]$
然后因为要组合数取模,得用上Lucas定理
//minamoto
#include<cstdio>
#define ll long long
const int N=1e6+;
ll inv[N],fac[N],val[N],dp[N],n,mod;
#define min(a,b) ((a)<(b)?(a):(b))
ll qpow(ll x,ll y){
ll res=;
while(y){
if(y&) res=res*x%mod;
y>>=,x=x*x%mod;
}
return res;
}
void init(){
int k=min(n,mod-);
fac[]=fac[]=;
for(int i=;i<=k;++i) fac[i]=fac[i-]*i%mod; inv[k]=qpow(fac[k],mod-);
for(int i=k-;i;--i) inv[i]=(i+)*inv[i+]%mod;
}
ll C(ll n,ll m){
if(m>n) return ;
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
ll Lucas(ll n,ll m){
if(m==||m==n) return ;
return Lucas(n/mod,m/mod)*C(n%mod,m%mod)%mod;
}
int main(){
//freopen("testdata.in","r",stdin);
scanf("%lld%lld",&n,&mod);init();
for(int i=n;i;--i){
val[i]=;if((i<<)<=n) val[i]+=val[i<<];if((i<<|)<=n) val[i]+=val[i<<|];
if((i<<|)<=n) dp[i]=Lucas(val[i]-,val[i<<])*dp[i<<]%mod*dp[i<<|]%mod;
else if((i<<)<=n) dp[i]=dp[i<<];
else dp[i]=;
}
printf("%lld\n",dp[]);
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]排列计数 组合数学+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]排列计数
题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很 ...
- 洛谷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\) 各出现了多少次? 解题思路: 使用 ...
- 洛谷 P2602 [ZJOI2010]数字计数
洛谷 第一次找规律A了一道紫题,写篇博客纪念一下. 这题很明显是数位dp,但是身为蒟蒻我不会呀,于是就像分块打表水过去. 数据范围是\(10^{12}\),我就\(10^6\)一百万一百万的打表. 于 ...
随机推荐
- 机器学习:逻辑回归(OvR 与 OvO)
一.基础理解 问题:逻辑回归算法是用回归的方式解决分类的问题,而且只可以解决二分类问题: 方案:可以通过改造,使得逻辑回归算法可以解决多分类问题: 改造方法: OvR(One vs Rest),一对剩 ...
- MySQL 备份脚本--mysqldump在slave 上进行备份
MySQL 备份脚本--mysqldump在slave 上进行备份 使用mysqldump在slave上进行备份,建议使用stop slave sql_thread,start slave sql_t ...
- IDEA编译器如何去掉注释中参数错误的提示
在使用idea的导入别人的项目的时候经常会在方法注释中出现参数错误的提示,这时我们可以参考下面的配置,将方法注释中的参数错误的提示,更新为警告提示~~ 具体使用方法,参考下图~
- C Primer Plus学习笔记(一)- C语言概述
从一个简单的C语言程序开始 #include <stdio.h> /*这是一个简单的C语言程序*/ //注释 int main(void) { int num; num = 1; prin ...
- Java中弱引用、软引用、虚引用及强引用的区别
Java中弱引用VS软引用 Java中有如下四种类型的引用: 强引用(Strong Reference) 弱引用(WeakReference) 软引用(SoftReference) 虚引用(Phant ...
- 问题:C#将base64转换成二进制图片;结果:c# Base64编码和图片的互相转换代码
c# Base64编码和图片的互相转换代码 Base64编码在Web方面有很多应用,譬如在URL.电子邮件方面.网上有很多相关的资源用于提供Base64编码和其他编码的转换,.Net Framewor ...
- 一个hitbernate配置文件,带几个表(注意mapping);如果连接字符串没有设置utf-8,向insert mysql 会产生乱码(utf8 或 utf-8)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuratio ...
- ES6中变量的解析赋值的用途
变量的解构赋值用途很多. (1)交换变量的值 let x = 1; let y = 2; [x, y] = [y, x]; 上面代码交换变量x和y的值,这样的写法不仅简洁,而且易读,语义非常清晰. ( ...
- JS中的数组排序函数sort()
JavaScript实现多维数组.对象数组排序,其实用的就是原生的sort()方法,用于对数组的元素进行排序. sort() 方法用于对数组的元素进行排序.语法如下: arrayObject.sort ...
- eclipse中安装git插件
1 安装及配置git插件,问度娘即可 点击前往 2 eclipse 中怎么同步到 本地git仓库 和 码云远程仓库 点击前往