这东西还是挺有思想的,道听途说一些东西,问问DuanYue同志,然后自己打表画树推了推,就搞出来了。

首先根据p i>p i/2(向下取整)这种形式,如果线段树学的好的人,一定能看出来,这是在唯一标号法标号后的形式,即父亲的权值大于两个儿子的权值,这是一个小根堆的样子。

那问题就是求给定数目的数字,求其能构成小根堆的个数。

这是一个类似树形dp的问题,我们设f[i]表示以当前节点为根所能构成小根堆的个数,那么有状态转移方程:

就是说当前节点及其子树一共分配了size[i]个数字,然后分给了左右子树,有上式Combine种可能,然后把左右儿子的贡献转移上来。

组合数还是老规矩打阶乘及其逆元的表,用lucas定理求一下,因为不用的话模数小的时候会崩,模数大了lucas也可以自动求组合取模。

实现过程中没有定义dp数组(其实size数组也没必要),直接带返回值的dfs搞一下。

代码略丑,勿看(主要是懒,直接define int long long 了)。

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#define int long long
using namespace std;
int n,p;
int size[];
int fac[],inv[];
int qpow(int x,int k){
int ans=;
for(;k;k>>=,x=1ll*x*x%p)
if(k&) ans=1ll*ans*x%p;
return ans;
}
void pre(){
fac[]=;
for(int i=;i<min(n,p);i++)
fac[i]=1ll*fac[i-]*i%p;
inv[min(n,p)-]=qpow(fac[min(n,p)-],p-);
for(int i=min(n,p)-;i>=;i--)
inv[i-]=1ll*inv[i]*i%p;
}
int com(int x,int y){
if(y>x) return ;
return ((1ll*fac[x]*inv[y])%p*inv[x-y]%p)%p;
}
int lucas(int x,int y){
if(!y) return ;
return com(x%p,y%p)*lucas(x/p,y/p)%p;
}
int dfs(int x){
if(x>n) return ;
size[x]++;
int a=dfs(x<<)%p;
int b=dfs(x<<|)%p;
size[x]+=size[x<<]+size[x<<|];
return 1ll*((a*b)%p*(lucas(size[x]-,size[x<<])%p))%p;
}
signed main(){
scanf("%lld%lld",&n,&p);
pre();
/*for(int i=1;i<=p;i++)
cout<<fac[i]<<" ";cout<<endl;
for(int i=1;i<=p;i++)
cout<<inv[i]<<" ";cout<<endl;*/
printf("%lld",dfs()%p);
return ;
}

Zjoi2010排列计数Perm的更多相关文章

  1. 【BZOJ2111】[ZJOI2010]排列计数(组合数学)

    [BZOJ2111][ZJOI2010]排列计数(组合数学) 题面 BZOJ 洛谷 题解 就是今年九省联考\(D1T2\)的弱化版? 直接递归组合数算就好了. 注意一下模数可以小于\(n\),所以要存 ...

  2. [ZJOI2010]排列计数 (组合计数/dp)

    [ZJOI2010]排列计数 题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有 ...

  3. 洛谷 P2606 [ZJOI2010]排列计数 解题报告

    P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...

  4. P2606 [ZJOI2010]排列计数

    P2606 [ZJOI2010]排列计数 因为每个结点至多有一个前驱,所以我们可以发现这是一个二叉树.现在我们要求的就是以1为根的二叉树中,有多少种情况,满足小根堆的性质. 设\(f(i)\)表示以\ ...

  5. bzoj2111 [ZJOI2010]排列计数

    Description 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic ...

  6. 洛谷P2606 [ZJOI2010]排列计数(组合数 dp)

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

  7. [ZJOI2010]排列计数

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

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

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

  9. BZOJ2111:[ZJOI2010]排列计数——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=2111 https://www.luogu.org/problemnew/show/P2606#su ...

随机推荐

  1. MVC4学习要点记四

    一.使用原生SQL使用EF的一个优点就是自动帮我们生成SQL,这在常规情况下很方便,但有些情况下用EF却不适合.另外还有些特别复杂的语句,利用EF很难生成.所以,EF提供一组方法用来执行原生的SQL. ...

  2. ubuntu18.3完美安装qq

    创建一个脚本全自动安装 #!/bin/bash # 安装 deepin-wine sudo mkdir deepin-wine deepin-qq cd deepin-wine git clone h ...

  3. spring AOP的相关术语

    连接点:Joinpoint   其实业务层接口的方法 切入点:Pointcut 被增强的是切入点,没被增强是永远都是连接点.连接点不一定是切入点,切入点一定是连接点 通知:Advice 就是指要增强的 ...

  4. 前段js实时判断会话是否超时

    前端自行判断页面是否超时 jsp从后台获取到回话时间var sessionTime="${sessionTime}"; js中 //实时判断会话是否超时 var lastSessi ...

  5. elementui按需加载

    定义一个ele.js文件 官网:https://element.eleme.io/#/zh-CN/component/quickstart // 方法1 import 'element-ui/lib/ ...

  6. vue项目性能优化总结

    在使用elementUI构建公司管理系统时,发现首屏加载时间长,加载的网络资源比较多,对系统的体验性会差一点,而且用webpack打包的vuejs的vendor包会比较大.所以通过搜集网上所有对于vu ...

  7. tensorflow-解决3个问题

    问题一:对特征归一化 Min-Max Scaling: X′=a+(X−Xmin)(b−a)/(Xmax−Xmin) # Problem 1 - Implement Min-Max scaling f ...

  8. vlan linux内核数据流程

    转:http://blog.sina.com.cn/s/blog_62bbc49c0100fs0n.html 一.前言 前几天做协议划分vlan的时候看了一些linux内核,了解不深,整理了下vlan ...

  9. 1.1.EJB概述

    1.EJB概述: Enterprice JavaBeans是一个用于分布式业务应用的标准服务端组件模型.采用Enterprice JavaBeans架构编写的应用是可伸的.事务性的. 多用户安全的.采 ...

  10. 解决docker容器的窗口大小问题

    解决docker容器的窗口大小问题 最近哥们在是使用docker时,发现有些容器内部窗口大小有问题. 如下午所示,vi窗口只占据左上角一部分.正常情况下vi应该铺满整个窗口才对呀. 所以哥们找到了解决 ...