zoukankan      html  css  js  c++  java
  • BZOJ_2111_[ZJOI2010]Perm 排列计数_树形DP+组合数学

    Description

    称一个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

    Sample Output

    16

    HINT

    100%的数据中,1 ≤ ��� N ≤ 106, P��� ≤ 10^9,p是一个质数。


    令fa[i]=i/2,就出现了一棵树。

    f[i]表示i的子树的排列方案数。

    siz[i]表示i的子树大小。

    f[x]*=f[to[i]]*C(siz[x]-1,siz[to[i]])。siz[x]是不断更新的。

    其中那个组合数的含义是每个儿子交错排列的方案数。

    有坑点,mod可能小于n。逆元需要分类讨论。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 1000050
    typedef long long ll;
    ll fac[N],inv[N],f[N];
    int siz[N],n,m,mod;
    int head[N],to[N<<1],nxt[N<<1],cnt;
    inline void add(int u,int v) {
        to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
    }
    ll qp(ll x,int y) {ll re=1; for(;y;y>>=1,x=x*x%mod) if(y&1) re=re*x%mod; return re;}
    void init() {
        int i;
        for(fac[0]=1,i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod;
        if(mod<=n) {
            inv[mod-1]=mod-1;
            for(i=mod-2;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
            for(i=mod;i<=n;i++) inv[i]=inv[i%mod];
        }else {
            inv[n]=qp(fac[n],mod-2);
            for(i=n-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
        }
    }
    ll C(int x,int y) {
        if(x<y) return 0;
        if(x<mod&&y<mod)
        return fac[x]*inv[y]%mod*inv[x-y]%mod;
        return C(x%mod,y%mod)*C(x/mod,y/mod)%mod;
    }
    void dfs(int x) {
        int i;
        f[x]=1;
        siz[x]=1;
        for(i=head[x];i;i=nxt[i]) {
            dfs(to[i]);
            siz[x]+=siz[to[i]];
            f[x]=f[x]*C(siz[x]-1,siz[to[i]])%mod*f[to[i]]%mod;
        }
    }
    int main() {
        scanf("%d%d",&n,&mod);
        init();
        int i;
        for(i=2;i<=n;i++) add(i>>1,i);
        dfs(1);
        printf("%lld
    ",f[1]);
    }
    
  • 相关阅读:
    1405ST软件测试课的要求补充说明
    软测实验课安排和考试
    Asp.Net 4.0 FormAuthentication 原理
    微信支付-“申请退款”接口遇到curl出错,错误码:58
    前端资源构建-Grunt环境搭建
    微信服务号开发-获取用户位置信息
    微信支付开发-当前页面的URL未注册
    Using Redis to store php session
    nginx performance monitor
    thinkphp nginx php-fpm url rewrite 导致 404 错误
  • 原文地址:https://www.cnblogs.com/suika/p/9427265.html
Copyright © 2011-2022 走看看