• 组合数学起步-排列计数[ZJOI2010][BZOJ2111]


    数据范围:$1 leq N leq 10^6, P leq 10^9 $
    这个题……
    以为是排列,其实是组合
    题目中说是从所有排列中找到Magic的,就是
    $p_{i/2} leq p_i$ 满足的情况
    我拿着排列想了半天,发现
    这个题和排列一点关系也没有
    而且我打了几个表,看了下可行结果,也不能逆向求
    后来是一个提示:用堆,dp
    堆啊……
    我扯了一会大根堆,发现堆的形态有不确定性,dp起来费力耗时

    所以就是小根堆了:小根堆的形态不变,只要找填数的方案,小根堆

    那么这里如何做呢?

    对于每一个叶子节点和唯一值,只有一种方案

    然后对于根节点,比根大的数作为叶节点,只要分成两部分就可以

    但是如何分也不必要记录,只要记录方案数

    由于是分步求解,

    所以要把每个子树上的方法与本次分的方法相乘。

    式子:$dp[i]=C_{siz[i]-1}^{siz[2*i]}*dp[i*2]*dp[i*2+1]$其中$siz[i]$是以$i$为根的树节点数

    于是就可以得到结果$dp[1]$

    当然要从$n$跑到$1$了

    下面是另一部分

    $C_n^m\%p$怎么求?

    卢卡斯定理,p一定要是素数。

    具体证明和代码见这里

    蒟蒻不会了~~

     然后里面的细节就是,求阶乘及其逆元,可以打表,现求逆元也可以。

    用 $a^{p-2}$ 的快速幂求逆元

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #define N 2000100
     5 #define LL long long
     6 using namespace std;
     7 LL p,n;
     8 int siz[N];
     9 LL fac[N],inv[N],dp[N];
    10 LL ppow(LL a,LL b){
    11     LL k=1;
    12     while(b){
    13         if(b&1)k=k*a%p;
    14         a=a*a%p;
    15         b>>=1;
    16     }
    17     return k;
    18 }
    19 void prerun(){
    20     for (int i=n;i>=1;i--){
    21         siz[i]=siz[i*2]+siz[i*2+1]+1;
    22     }
    23     fac[0]=1;
    24     for (int i=1;i<=n;i++){
    25         fac[i]=fac[i-1]*i%p;
    26     }
    27 }
    28 LL C(LL m,LL n){
    29     if(n<m)return 0;
    30     return fac[n]*ppow(fac[m],p-2)%p*ppow(fac[n-m],p-2)%p;
    31 }
    32 LL lucas(LL m,LL n){
    33     if(m==0)return 1;
    34     return lucas(m/p,n/p)*C(m%p,n%p)%p;
    35 }
    36 int main (){
    37     scanf("%lld%lld",&n,&p);
    38     prerun();
    39     for (int i=n;i>=1;i--){
    40         dp[i]=lucas(siz[i*2],siz[i]-1);
    41         if(i*2<=n)dp[i]=dp[i]*dp[i*2]%p;
    42         if(i*2+1<=n)dp[i]=dp[i]*dp[i*2+1]%p;
    43     }
    44     printf("%lld
    ",dp[1]);
    45     return 0;
    46 }
    View Code

    真不知道没有题解怎么活~~

    主要参考:Rorschach_XR的[ZJOI2010]排列计数 题解

    Miemeng真的蒻
  • 相关阅读:
    [Oracle整理]synonym及其应用
    [Oracle整理]Oracle之Procedure参数类型
    [Oracle整理]Oracle之数组
    RDL之矩陣
    [Oracle整理]数据类型大全
    [Oracle整理]Oracle之ROWTYPE和RECORD
    [Oracle整理]Oracle游标(显示游标&隐式游标&动态游标&参数游标)
    报表rdl嵌入网页(ASP.NET)
    Linux物理机忘记root密码
    python ftplib下载文件封装
  • 原文地址:https://www.cnblogs.com/kalginamiemeng/p/11130663.html
Copyright © 2020-2023  润新知