题目大意

  求满足下列条件的排列$P$的数量:$\forall P_i, P_i>P_{\lfloor \frac{i}{2}\rfloor}$。

思路

从下标入手

  反过来想,也就是对$\forall P_i, P_i<P_{2i}且P_i<P_{2i+1}$。因为小根堆中一个“小三角”中节点的编号满足:若顶部编号为$i$,则左下角节点编号为"2i",右下角为$2i+1$,因此题目就是要让我们求大小为$n$的小根堆的数量。

递归式

  因为堆这个结构有“子堆”这个子结构,所以可以递归。定义$l(n)$为大小为$n$的堆的左子堆大小,$f(i)$为大小为$i$,所有节点的值的取值范围一定(但并没有具体指定)时都不相等的堆有多少个。该堆的左子堆的个数等于当左子堆所有节点的值的取值范围的种数($C_{n-1}^{l(n)}$)乘以当所有节点的值的取值范围一定时的堆数($f(l(n))$)。分析完左子堆,随后还要乘以右子堆的堆数($f(r(n))$)。由于左子堆取值范围的种数确定了,右子堆的也确定了,所以不用再次乘以$C_{n-1}^{r(n)}$了。故总递归式为:

$$f(n)=C_{n-1}^{l(n)}f(l(n))f(r(n))$$

  注意求组合数时要用Lucas定理取模。

怎么求$l(n),r(n)$?

  注意这个没有通项公式,要按照堆的顺序递归解决。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; #define ll long long
const int MAX_N = 1000010;
ll F[MAX_N], Fact[MAX_N];
int Size_Lsize[MAX_N], Size_Rsize[MAX_N]; int GetSize(int curNode, int n)
{
if (curNode > n)
return 0;
int lSize = GetSize(curNode * 2, n), rSize = GetSize(curNode * 2 + 1, n), curSize = lSize + rSize + 1;
Size_Lsize[curSize] = lSize, Size_Rsize[curSize] = rSize;
return curSize;
} void GetFact(int n, int p)
{
Fact[0] = Fact[1] = 1;
for (ll i = 2; i <= n; i++)
Fact[i] = i * Fact[i - 1] % p;
} ll Mult(ll a, ll b, ll p)
{
ll ans = 0;
while (b)
{
if (b & 1)
ans = (ans + a) % p;
a = (a + a) % p;
b >>= 1;
}
return ans;
} ll Power(ll a, ll n, ll p)
{
ll ans = 1;
while (n)
{
if (n & 1)
ans = Mult(ans, a, p);
a = Mult(a, a, p);
n >>= 1;
}
return ans;
} ll Inv(ll a, ll p)
{
return Power(a, p - 2, p);
} ll Comb(int n, int m, int p)
{
return Fact[n] * Inv(Mult(Fact[n - m], Fact[m], p), p);
} ll Lucas(int n, int m, int p)
{
if (m == 0)
return 1;
return Comb(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
} ll Dfs(int n, int p)
{
if (F[n])
return F[n];
if (n == 1 || n == 0)
return F[n] = 1;
return F[n] = Dfs(Size_Lsize[n], p) * Dfs(Size_Rsize[n], p) % p * Lucas(n - 1, Size_Lsize[n], p) % p;//易忘点:Dfs后的%p
} int main()
{
int n;
ll p;
scanf("%d%lld", &n, &p);
GetSize(1, n);
GetFact(n, p);
printf("%lld\n", Dfs(n, p));
return 0;
}

  

luogu2606 排列计数的更多相关文章

  1. BZOJ 4517: [Sdoi2016]排列计数

    4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 911  Solved: 566[Submit][Status ...

  2. bzoj-4517 4517: [Sdoi2016]排列计数(组合数学)

    题目链接: 4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 846  Solved: 530[Submit][ ...

  3. ACM/ICPC 之 DP-浅谈“排列计数” (POJ1037)

    这一题是最近在看Coursera的<算法与设计>的公开课时看到的一道较难的DP例题,之所以写下来,一方面是因为DP的状态我想了很久才想明白,所以借此记录,另一方面是看到这一题有运用到 排列 ...

  4. 数学(错排):BZOJ 4517: [Sdoi2016]排列计数

    4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 693  Solved: 434[Submit][Status ...

  5. 【数论·错位排列】bzoj4517 排列计数

    4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 1428  Solved: 872[Submit][Statu ...

  6. BZOJ 4517: [Sdoi2016]排列计数 [容斥原理]

    4517: [Sdoi2016]排列计数 题意:多组询问,n的全排列中恰好m个不是错排的有多少个 容斥原理强行推♂倒她 $恰好m个不是错排 $ \[ =\ \ge m个不是错排 - \ge m+1个不 ...

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

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

  8. bzoj4517排列计数 错排+组合

    4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 1491  Solved: 903[Submit][Statu ...

  9. BZOJ_4517_[Sdoi2016]排列计数_组合数学

    BZOJ_4517_[Sdoi2016]排列计数_组合数学 Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[ ...

随机推荐

  1. word文档去掉复制过来的背景颜色

    选择清除格式

  2. Windows phone开发 页面布局之屏幕方向

    (博客部分内容参考Windows phone开发文档) Windows phone的屏幕方向是利用Windows phone设备的方向传感器提供的数据实现切换的. Windows Phone支持纵向和 ...

  3. 基于bootstarp的Dailog

    oaoDailog开发帮助 1.         帮助文档关键字 boostrap模态框oaoDailog 2.         使用场景 当网页上点击某个按钮需要给予用户提示确认,用户点击确认按钮才 ...

  4. 前端HTML5思维导图笔记

    看不清的朋友右键保存或者新窗口打开哦!热爱学习前端,喜欢我可以关注我,更多的思维导图笔记

  5. matplotlib之pyplot 知识点滴

    以下是一些常用地址链接,请参考 matplotlib 官方网址 plt.plot()函数细节 Matplotlib 中文用户指南 4.6 编写数学表达式 Python seaborn matplotl ...

  6. android 将手机号中间隐藏为星号(*)

    ){ StringBuilder sb =new StringBuilder(); ; i < pNumber.length(); i++) { char c = pNumber.charAt( ...

  7. Matlab/Eigen矩阵填充问题

    Matlab进行矩阵填充时可以填充空矩阵,相当于空矩阵不存在,例如一下代码: P_RES = [ P_xv P_xvy P_xv*dy_dxv'; P_yxv P_y P_yxv*dy_dxv'; d ...

  8. NDK 使用STL

    参考链接:Android中使用STL 1. 在 Application.mk 中添加代码"APP_STL:= gnustl_static"后, 文件中的内容如下: APP_ABI ...

  9. express创建第一个web应用

    Express 在初始化一个项目的时候需要指定模板引擎,默认支持Jade和ejs. 这里我们使用ejs模板引擎:(关于ejs的介绍可以先从百科里面了解一个大概)EJS是一个JavaScript模板库, ...

  10. 3D模型在UI上显示的方法(Unity)

    方法:使用RawImage通过Render Texter将摄像机下的物体渲染纹理记录并显示在RawImage上面 具体实现:新建一个模型(Cube),新建一个摄像机,将Clear Flags设置为So ...