这东西还是挺有思想的,道听途说一些东西,问问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. 数据库SQL优化分析查询语句总结

    方法一: SELECT TOP 10 TEXT AS 'SQL Statement' ,last_execution_time AS 'Last Execution Time' ,(total_log ...

  2. 服务端相关知识学习(六)Zookeeper client

    Zookeeper的client是通过Zookeeper类提供的.前面曾经说过,Zookeeper给使用者提供的是一个类似操作系统的文件结构,只不过这个结构是分布式的.可以理解为一个分布式的文件系统. ...

  3. 转:git常用操作

    转自:https://www.cnblogs.com/donghaojun/p/10906981.html 开发常用git指令:git init  # 初始化本地git环境 git clone xxx ...

  4. 4.图片左轮播图(swiper)

    一.html部分 二.js部分 三.源代码部分 <body> <div id="box"> <img src="imges/111.jpg& ...

  5. centos7 php7.3

    ./configure --prefix=/root/php/php-7.3.10/output \ --with-mhash \ --with-openssl \ --with-mysqli=sha ...

  6. windows漏洞MS03_026

    话不多说,直接进入正题 第一步查看是否能ping通,第二步就是扫描端口,开放了端口才能进行攻击 linux进入msfconsole,搜索03_026 search 03_026 等待一会,返回漏洞的全 ...

  7. linux常用查看命令

    一般查看 cat -n 文件名 n 代表显示行号 分页查看 more 文件名 more -50 文件名 -50 代表一页显示50行 向下翻页  空格 向上翻页 b more +/搜索值 文件名 查找文 ...

  8. linux基础—课堂随笔09_数组

    数组:(6.14 第一节) 取分区利用率,大于百分之八十则发出警报 取分区第一列 取分区使用率: 脚本: 检查脚本语法: ——end 数组切片: 1.跳过前两个取后面 2.跳过前两个取三个 生成10个 ...

  9. springboot集成redis使用redis作为session报错ClassNotFoundException类RememberMeServices

    springboot 集成redis使用redis作为缓存,会报错的问题. 错误信息: java.lang.IllegalStateException: Error processing condit ...

  10. 数据库——Oracle(1)

    1 Oracle数据库:ORACLE数据库系统是美国ORACLE(甲骨文)研发并提供的款关系型数据库管理系统,占据市场的主要的份额. 目前常用版本:Oracle9i,Oracle10g,Oracle1 ...