题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2111

题意:

  给定n,p,问你有多少个1到n的排列P,对于任意整数i∈[2,n]满足P[i]>P[i/2]。

  保证p为质数,输出答案 mod p的值。(n <= 10^6, p <= 10^9)

题解:

  对于每个i,分别向i*2和i*2+1连一条边。

  可以发现,最终形成的是一棵以1为根节点的二叉树。

  题目中P[i]>P[i/2]的条件,就变成了:P[fa]<P[son]

  然后就可以dp了。

  表示状态:

    dp[i]表示对于i的子树来说,填入1到siz[i]这些数,并且满足条件的方案数。

  找出答案:

    ans = dp[1]

  如何转移:

    对于i的子树来说,显然节点i只能填1。

    所以首先考虑的就是将2到siz[i]这些数分配给两个子树的方案数。

    设l = i*2, r = i*2+1,则方案数显然为C(siz[i]-1, siz[l])。

    所以dp[i] = C(siz[i]-1, siz[l]) * dp[l] * dp[r]

  边界条件:

    dp[leaf] = siz[leaf] = 1

  因为dp转移中要求组合数:C(n,m) = fact[n] * inv(fact[m]) * inv(fact[n-m])

  然而给定的p可能很小,以至于与要求逆元的数不互质。

  所以要用到Lucas定理求组合数:C(n,m)%p = C(n%p,m%p) * lucas(n/p,m/p) % p

AC Code:

 #include <iostream>
#include <stdio.h>
#include <string.h>
#define MAX_N 1000005
#define int ll using namespace std; typedef long long ll; int n,p;
int f[MAX_N];
int dp[MAX_N];
int siz[MAX_N]; void cal_f()
{
f[]=;
for(int i=;i<=n;i++) f[i]=f[i-]*i%p;
} void exgcd(int a,int b,int &x,int &y)
{
if(b==)
{
x=,y=;
return;
}
exgcd(b,a%b,y,x);
y-=(a/b)*x;
} int inv(int a)
{
int x,y;
exgcd(a,p,x,y);
return (x%p+p)%p;
} int c(int n,int m)
{
if(n<m) return ;
return f[n]*inv(f[m])%p*inv(f[n-m])%p;
} int lucas(int n,int m)
{
if(m==) return ;
return c(n%p,m%p)*lucas(n/p,m/p)%p;
} void dfs(int x)
{
dp[x]=siz[x]=;
int l=(x<<),r=((x<<)|);
if(l<=n) dfs(l),siz[x]+=siz[l],dp[x]=dp[x]*dp[l]%p;
if(r<=n) dfs(r),siz[x]+=siz[r],dp[x]=dp[x]*dp[r]%p;
if(l<=n) dp[x]=dp[x]*lucas(siz[x]-,siz[l])%p;
} signed main()
{
cin>>n>>p;
cal_f();
dfs();
cout<<dp[]<<endl;
}

BZOJ 2111 [ZJOI2010]Perm 排列计数:Tree dp + Lucas定理的更多相关文章

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

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

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

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

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

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

  4. bzoj 2111: [ZJOI2010]Perm 排列计数【树形dp+lucas】

    是我想复杂了 首先发现大于关系构成了一棵二叉树的结构,于是树形dp 设f[i]为i点的方案数,si[i]为i点的子树大小,递推式是\( f[i]=f[i*2]*f[i*2+1]*C_{si[i]-1} ...

  5. bzoj 2111: [ZJOI2010]Perm 排列计数 Lucas

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

  6. bzoj 2111: [ZJOI2010]Perm 排列计数

    神题... 扒自某神犇题解: http://blog.csdn.net/aarongzk/article/details/50655471 #include<bits/stdc++.h> ...

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

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

  8. 【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是素数 ...

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

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

随机推荐

  1. SVN中分支的建立与合并

    转载    出处:http://yaozhong1988.blog.163.com/blog/static/141737885201162671635126/ 一.  SVN分支的意义:     简单 ...

  2. jQuery 文档操作方法(append)

    这些方法对于 XML 文档和 HTML 文档均是适用的,除了:html(). 一.append() 方法 append() 方法在被选元素的结尾(仍然在内部)插入指定内容. 例子: <html& ...

  3. SpringBoot处理url中的参数的注解

    1.介绍几种如何处理url中的参数的注解 @PathVaribale  获取url中的数据 @RequestParam  获取请求参数的值 @GetMapping  组合注解,是 @RequestMa ...

  4. 3.5.基于STC89C52+MC20的短信远程控制开关LCD1602显示

    需要准备的硬件 MC20开发板 1个 https://item.taobao.com/item.htm?id=562661881042 GSM/GPRS天线 1根 https://item.taoba ...

  5. mysql数据库补充知识6 完整性约束

    一 介绍 约束条件与数据类型的宽度一样,都是可选参数 作用:用于保证数据的完整性和一致性主要分为: PRIMARY KEY (PK) 标识该字段为该表的主键,可以唯一的标识记录 FOREIGN KEY ...

  6. 剑指offer 面试52题

    面试52题: 题目:两个链表的第一个公共节点 题:输入两个链表,找出它们的第一个公共节点. 解题思路: ①蛮力法:在第一个链表上顺序遍历每个节点,每遍历到一个节点,就在第二个链表上顺序遍历每个节点,直 ...

  7. openstack ocata版(脚本)控制节点安装

    一.初始化环境: 1.更换yum源: yum install -y wget mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS- ...

  8. UI设计中的各种小控件

    xib支持图形化操作,提供了几乎所有的控件可供选择,只需拖动到相应的位置即可,但是控件的后台代码仍然需要手动编写,一定程度上加速了前台的开发. xib快速开发程序,手写代码速度比较慢 xib适合做静态 ...

  9. MFC输出调试信息

    刚学mfc时只知道用MessageBox输出,可是MessageBox只能输出字符串, 对于习惯于printf的我来说非常不便,后来查了一下mfc可以像printf一样输出, 就是TRACE这个宏,用 ...

  10. Android开发BUG及解决方法

    错误描述 问题1: 按照提示打开gradle-wrapper.properties文件 并且将gradle-2.8-all.zip改为gradle-2.10-all.zip,重新导入项目 问题2: 却 ...