zoukankan      html  css  js  c++  java
  • [Lucas][树形dp][组合] Bzoj P2111 Perm 排列计数

    Description

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

    题解

    • 把i/2看作i和i+1的父亲,然后这样就会形成一棵完全二叉树
    • 那么就可以考虑树形dp,设f[i]表示从i到n的方案数,size[i]表示第i个数的子树大小
    • 那么如果i*2>n,那么f[i]=1,如果i*2==n,那么f[i]=f[i*2]
    • 如果i*2+1<=n,那么f[i]=f[i*2]*f[i*2+1]*C(size[i*2],size[i]-1)
    • 还是要用Lucas定理来搞

    代码

     1 #include <cstdio>
     2 #include <iostream>
     3 #define N 1000010
     4 #define ll long long
     5 using namespace std;
     6 int n,p,size[N];
     7 ll inv[N],fac[N],f[N];
     8 ll C(ll n,ll m) { return m>n?0:(n<p?fac[n]*inv[m]%p*inv[n-m]%p:C(n/p,m/p)*C(n%p,m%p)); }
     9 int main()
    10 {
    11     scanf("%d%d",&n,&p),fac[0]=inv[0]=inv[1]=1;
    12     for (int i=1;i<=min(n,p-1);i++) fac[i]=fac[i-1]*i%p;
    13     for (int i=2;i<=min(n,p-1);i++) inv[i]=(p-p/i)*inv[p%i]%p;
    14     for (int i=2;i<=min(n,p-1);i++) inv[i]=(inv[i]*inv[i-1])%p;
    15     for (int i=n;i;i--)
    16         if (i*2+1<=n) size[i]=1+size[i*2]+size[i*2+1],f[i]=f[2*i]*f[2*i+1]%p*C(size[i]-1,size[2*i])%p;
    17         else if (i*2<=n) size[i]=1+size[i*2],f[i]=f[2*i];
    18         else size[i]=f[i]=1;
    19     printf("%lld",f[1]);
    20 }
  • 相关阅读:
    python自动化测试学习路线-python设计语言sys模块argv参数用法
    python自动化测试学习路线-python设计语言serial模块调用方法
    【考研复习】线性代数矩阵部分-题解
    【考研复习
    Windows提权
    Hash算法——加密解密说明
    AES 加密算法的原理详解
    sqlmap常用命令
    curl的使用
    DOM XSS详解
  • 原文地址:https://www.cnblogs.com/Comfortable/p/11335187.html
Copyright © 2011-2022 走看看