problem

luogu-P2606

solution

我们对 i−⌊i2⌋i-\lfloor\frac i2\rfloori−⌊2i​⌋ 远没有 i−2∗i,2∗i+1i-2*i,2*i+1i−2∗i,2∗i+1 敏感,这其实就是个二叉树,而且是个小根堆。

每个点的值都小于左右儿子的值(如果有左右儿子)。

设 f(i):f(i):f(i): 树大小为 iii 的合法方案数。

树根肯定是定了的,然后从剩下的 i−1i-1i−1 个数中选左子树大小个数,剩下自然都归为右子树。

f(i)=f(sizlson)∗(i−1sizlson)f(i)=f(siz_{lson})*\binom{i-1}{siz_{lson}}f(i)=f(sizlson​)∗(sizlson​i−1​)。

组合数只是起分配编号的作用,分配后离散化成 1,2,...,j1,2,...,j1,2,...,j。

比如:对于 f(5)f(5)f(5) 而言,根是 111,p(1)=1p(1)=1p(1)=1 是固定的。

但是分给左子树的编号可能是 (2,3,4),(2,3,5),(2,4,5),(3,4,5)(2,3,4),(2,3,5),(2,4,5),(3,4,5)(2,3,4),(2,3,5),(2,4,5),(3,4,5) 有四种情况。

但是离散化后都是 (1,2,3)(1,2,3)(1,2,3)。

而 f(3)f(3)f(3) 计算的就是当其被分配的编号为 (1,2,3)(1,2,3)(1,2,3) 的时候的方案数。

这里面是嵌套下去的递归过程,分配编号方案数,拿到离散化的编号,继续往字数分配编号…直到树大小为 1/2/31/2/31/2/3,再开始层层回溯计算总方案数。

整个问题编号为 1∼n1\sim n1∼n,离散化后也是 1∼n1\sim n1∼n,所以 f(n)f(n)f(n) 没有分配编号的多种方案数。

所以 f(i)f(i)f(i) 只是计算分配给其的离散化的连续编号然后是小根堆的答案。

这里的坑点是 nnn 可能 >m>m>m。所以预处理阶乘和逆元要注意上限的限制到底是多少。

code

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 1000005
int n, p;
int fac[maxn], inv[maxn], siz[maxn], f[maxn], lg[maxn];int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % p;x = x * x % p;y >>= 1;}return ans;
}int calc( int n, int m ) {if( n < m ) return 0;else return fac[n] * inv[m] % p * inv[n - m] % p;
}int C( int n, int m ) {if( ! m ) return 1;return C( n / p, m / p ) * calc( n % p, m % p ) % p;
}#define lson i << 1
#define rson i << 1 | 1signed main() {scanf( "%lld %lld", &n, &p );fac[0] = inv[0] = 1, lg[0] = -1;for( int i = 1;i <= n;i ++ ) lg[i] = lg[i >> 1] + 1;int lim = min( n, p - 1 );for( int i = 1;i <= lim;i ++ ) fac[i] = fac[i - 1] * i % p;inv[lim] = qkpow( fac[lim], p - 2 );for( int i = lim - 1;i;i -- ) inv[i] = inv[i + 1] * ( i + 1 ) % p;f[1] = f[2] = 1, f[3] = 2;for( int i = 4, l = 1, r = 1;i <= n;i ++ ) {if( i - (1 << lg[i]) + 1 <= (1 << lg[i] - 1) ) l ++;else r ++;f[i] = C( i - 1, l ) * f[l] % p * f[r] % p;}printf( "%lld\n", f[n] % p );return 0;
}

[ZJOI2010] 排列计数(dp + 组合数)相关推荐

  1. 洛谷P2606 [ZJOI2010]排列计数(数位dp)

    题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很 ...

  2. 【bzoj2111】[ZJOI2010]Perm 排列计数 dp+Lucas定理

    题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Mogic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Mogic的,答案可能很 ...

  3. ●洛谷P2606 [ZJOI2010]排列计数

    题链: https://www.luogu.org/problemnew/show/P2606 题解: 组合数(DP),Lucas定理 首先应该容易看出,这个排列其实是一个小顶堆. 然后我们可以考虑d ...

  4. Zjoi2010排列计数Perm

    这东西还是挺有思想的,道听途说一些东西,问问DuanYue同志,然后自己打表画树推了推,就搞出来了. 首先根据p i>p i/2(向下取整)这种形式,如果线段树学的好的人,一定能看出来,这是在唯 ...

  5. 【BZOJ4517】排列计数,组合数+错排

    传送门 题意就是数字1-n任意排列,要求有m个数,放在它们各自对应的位置上(就是1放在位置1上,2放在位置2上--),剩下n-m个数全部不在对应的位置上(比如3不在位置3上,4不在位置4上),求排列的 ...

  6. [CQOI2017] 老C的键盘(树形dp + 组合数)

    problem luogu-P3757 solution observation:\text{observation}:observation: hi/2−hih_{i/2}-h_ihi/2​−hi​ ...

  7. 【组合数学】排列组合 ( 多重集组合数示例 | 三个计数模型 | 选取问题 | 多重集组合问题 | 不定方程非负整数解问题 )

    文章目录 一.多重集组合示例 二.三个计数模型 排列组合参考博客 : [组合数学]基本计数原则 ( 加法原则 | 乘法原则 ) [组合数学]集合的排列组合问题示例 ( 排列 | 组合 | 圆排列 | ...

  8. [2019 牛客CSP-S提高组赛前集训营4题解] 复读数组(数论)+ 路径计数机(数上DP)+ 排列计数机(线段树+二项式定理)

    文章目录 T1:复读数组 题目 题解 代码实现 T2:路径计数机 题目 题解 代码实现 T3:排列计数机 题目 题解 CODE T1:复读数组 题目 有一个长为n×k的数组,它是由长为n的数组A1,A ...

  9. bzoj 4517: [Sdoi2016]排列计数(错排+组合数逆元)

    4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MB Submit: 1259  Solved: 766 [Submit][Sta ...

最新文章

  1. python密码学编程pdf-Python密码学编程PDF电子书免费下载
  2. 基于协同训练的半监督文本分类算法
  3. java线程基础巩固---线程生命周期以及start方法源码剖析
  4. 每个人都知道MVC…
  5. JAVA中的MDC类_CMake - 用/ MT而不是/ MD编译
  6. 此博客不再更新,新博客地址https://xsamsara.tk/
  7. MySql数据的启动和停止以及SQLyog图形化工具的下载
  8. 教你win10原版镜像怎么安装
  9. junit5 入门系列教程-05-junit5 断言(assert)
  10. STM32 tjpgd软件JPEG解码后RGB888数据格式问题
  11. amd服务器epyc系列,AMD在市场上有EPYC系列的两个版本
  12. Deadlock found when trying to get lock; try restarting transaction 【MySQL死锁问题解决】
  13. 一劳永逸安装程序无法继续 Microsoft Runtime DLL 安装程序未能完成安装
  14. mysql 1114错误_mysql出现错误编码1114怎么办
  15. mysql交并补_集合交并补运算顺序是什么?
  16. idhttp的socket error # 10054 错误的处理办法
  17. Windows引导过程(BIOS,UEFI)
  18. Kali之——设置静态IP
  19. no matching host key type found. Their offer: ssh-rsa
  20. 机器学习算法竞赛平台整理

热门文章

  1. 老是担心数学学不好?这些基础是时候正视了!
  2. 震撼!英伟达用深度学习做图像修复,毫无ps痕迹
  3. python tkinter进度条_在python3.7中更新tkinter进度条
  4. linux中获取redis的map,深入Redis之 bitmap位图和HyperLogLog(五)
  5. 修改图层的范围_【PS|第39期】数字绘画 使用填充图层
  6. python对象_查找Python对象具有的方法
  7. 计算机所有数据的表示方式都是用,计算机数据表示
  8. linux远程登录命令rlogin,Linux rlogin命令
  9. Java手撕Linkedlist(双向链表)基本用法的实现
  10. C++ 学习之旅(7)——指针pointer