[ZJOI2010]Perm

题目

称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很大,只能输出模P以后的值

INPUT

输入文件的第一行包含两个整数 n和p,含义如上所述。

OUTPUT

输出文件中仅包含一个整数,表示计算1,2,?, ???的排列中, Magic排列的个数模 p的值。

SAMPLE

INPUT

20 23

OUTPUT

16

解题报告

这竟然是一道树规= =

其实想明白之后挺简单的

我们考虑一颗满二叉树,一个节点$i$如果有左儿子,那么它的左儿子编号一定为$i\times 2$,如果它有右儿子,那么它的右儿子编号一定为$i\times 2+1$

再回来看这道题,假如我们建一颗满二叉树,那么问题不就转化成所有儿子的权值都比父亲的权值大的方案数么?

设$f[size[i]]$代表编号为$i$的节点的方案数

我们要取出$i-1$个(把自己去掉)比它大的数,一部分放在左子树,一部分放在右子树,且当左子树确定了取出哪些数时,右子树所取出的数也是一定的

故我们可以推出状态转移方程:

$$f[size[i]]=C_{size[i]-1}^{size[i<<1]}\times f[size[i<<1]]\times f[size[i<<1|1]]$$

然后实现即可

 #include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long L;
L n,p;
L fac[];
inline L po(L x,L hm){
L ret();
while(hm){
if(hm&)
ret=ret*x%p;
x=x*x%p;
hm>>=;
}
return ret;
}
inline L C(int n,int m){
return fac[n]*po(fac[m],p-)%p*po(fac[n-m],p-)%p;
}
struct edge{
int e;
edge *n;
}a[],*pre[];
int tot;
inline void insert(int s,int e){
a[++tot].e=e;
a[tot].n=pre[s];
pre[s]=&a[tot];
}
int size[];
inline void get_size(int u){
size[u]=;
for(edge *i=pre[u];i;i=i->n){
int e(i->e);
if(!size[e]){
get_size(e);
size[u]+=size[e];
}
}
}
L f[];
inline void dfs(int u){
if(u>n){
// size[u]=0;
// f[0]=1;
return;
}
// cout<<u<<endl;
// size[u]=1;
dfs(u<<);
// size[u]+=size[u<<1];
dfs(u<<|);
// size[u]+=size[u<<1|1];
f[size[u]]=C(size[u]-,size[u<<])*f[size[u<<]]%p*f[size[u<<|]]%p;
}
inline int gg(){
// freopen("permzj.in","r",stdin);
// freopen("permzj.out","w",stdout);
scanf("%lld%lld",&n,&p);
fac[]=fac[]=;
for(int i=;i<=n;++i){
L tmp(i);
while(tmp%p==)
tmp/=p;
fac[i]=fac[i-]*tmp%p;
}
for(int i=;i<=n;++i){
if((i<<)>n)
break;
insert(i,i<<);
if((i<<|)>n)
break;
insert(i,i<<|);
}
get_size();
f[]=f[]=;
dfs();
printf("%lld",f[n]%p);
// for(int i=1;i<=n;++i)
// cout<<"i="<<i<<" size[i]="<<size[i]<<endl;
return ;
}
int K(gg());
int main(){;}

[ZJOI2010]Perm的更多相关文章

  1. BZOJ 2111: [ZJOI2010]Perm 排列计数 [Lucas定理]

    2111: [ZJOI2010]Perm 排列计数 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1936  Solved: 477[Submit][ ...

  2. 2111: [ZJOI2010]Perm 排列计数

    2111: [ZJOI2010]Perm 排列计数 链接 题意: 称一个1,2,...,N的排列$P_1,P_2...,P_n$是Magic的,当且仅当$2<=i<=N$时,$P_i> ...

  3. bzoj 2111: [ZJOI2010]Perm 排列计数 (dp+卢卡斯定理)

    bzoj 2111: [ZJOI2010]Perm 排列计数 1 ≤ N ≤ 10^6, P≤ 10^9 题意:求1~N的排列有多少种小根堆 1: #include<cstdio> 2: ...

  4. 【BZOJ2111】[ZJOI2010]Perm 排列计数 组合数

    [BZOJ2111][ZJOI2010]Perm 排列计数 Description 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi> ...

  5. BZOJ2111: [ZJOI2010]Perm 排列计数

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2111 题意:一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2< ...

  6. 【BZOJ】2111: [ZJOI2010]Perm 排列计数 计数DP+排列组合+lucas

    [题目]BZOJ 2111 [题意]求有多少1~n的排列,满足\(A_i>A_{\frac{i}{2}}\),输出对p取模的结果.\(n \leq 10^6,p \leq 10^9\),p是素数 ...

  7. bzoj 2111 [ZJOI2010]Perm 排列计数(DP+lucas定理)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2111 [题意] 给定n,问1..n的排列中有多少个可以构成小根堆. [思路] 设f[i ...

  8. [BZOJ2111][ZJOI2010]Perm排列计数(组合数学)

    题意就是求一个n个点的堆的合法形态数. 显然,给定堆中所有数的集合,则这个堆的根是确定的,而由于堆是完全二叉树,所以每个点左右子树的大小也是确定的. 设以i为根的堆的形态数为F(i),所以F(i)+= ...

  9. BZOJ 2111 [ZJOI2010]Perm 排列计数:Tree dp + Lucas定理

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2111 题意: 给定n,p,问你有多少个1到n的排列P,对于任意整数i∈[2,n]满足P[i ...

随机推荐

  1. telnet端口问题

    今天测试发现telnet 一个端口不通,开始还以为是服务开放这个端口有问题,后来才发现这个端口是udp的.而telnet下层走的tcp协议,自然无法测试那些tcp的端口. 而之前下意识里还总以为都可以 ...

  2. java enum int String 相互转换

    1.  enum<->int enum -> int: int i = enumType.value.ordinal(); int -> enum: enumType b= e ...

  3. P3390矩阵快速幂

    题目背景 矩阵快速幂 题目描述 给定n*n的矩阵A,求A^k 输入输出格式 输入格式: 第一行,n,k 第2至n+1行,每行n个数,第i+1行第j个数表示矩阵第i行第j列的元素 输出格式: 输出A^k ...

  4. [Swift通天遁地]五、高级扩展-(1)快速检测设备属性:版本、类型、屏幕尺寸

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  5. SpringBoot集成Mybatis配置动态数据源

    很多人在项目里边都会用到多个数据源,下面记录一次SpringBoot集成Mybatis配置多数据源的过程. pom.xml <?xml version="1.0" encod ...

  6. ios-判断手机上是否安装了某个App

    方法一     1.获取手机中安装的所有App   1.1.runtime中的方法,所以要导入       #include <objc/runtime.h>   1.2.在 AppDel ...

  7. Spring Boot (26) RabbitMQ延迟队列

    延迟消息就是指当消息被发送以后,并不想让消费者立即拿到消息,而是等待指定时间后,消费者才拿到这个消息进行消费. 延迟队列 订单业务: 在电商/点餐中,都有下单后30分钟内没有付款,就自动取消订单. 短 ...

  8. 【Spring】IOC

    浅谈IOC IOC的理论背景 图1:传统系统中,对象之间相互引用的一幅图,在采用面向对象方法设计的软件系统中,它的底层的实现都是由n个对象所组成的,所有的对象通彼此之间的合作最终实现系统的业务逻辑,如 ...

  9. Android O Bitmap 内存分配

      我们知道,一般认为在Android进程的内存模型中,heap分为两部分,一部分是native heap,一部分是Dalvik heap(实际上也是native heap的一部分).   Andro ...

  10. Android sensor 系统框架 (一)

    这几天深入学习了Android sensor框架,以此博客记录和分享分析过程,其中难免会有错误的地方,欢迎指出! 这里主要分析KERNEL->HAL->JNI这3层的流程.主要从以下几方面 ...