LOJ#6495. 「雅礼集训 2018 Day1」树

LOJ#6495. 「雅礼集训 2018 Day1」树

题目描述

有一棵 n 个点的有根树,点编号为1至n,其中1号点为根,除 1号点外,i号点的父亲在 1至 i -1 内均匀随机。

定义一棵树的深度为所有节点到根路径上节点数的最大值,求这棵树的期望深度。

题解

一道披着期望外衣的计数题

考虑 F[i][j]为I个点期望深度J点的个数

然后就按计数题做呗

因为2号点的父亲一定是一号点

就讨论一下深度最深的点是在2号节点对应的子树中还是其他子树中

#include<bits/stdc++.h>

#define LL long long

using namespace std;

inline LL read()
{
    LL f = 1 , x = 0;
    char ch;
    do
    {
        ch = getchar();
        if(ch=='-') f=-1;
    } while(ch<'0'||ch>'9');
    do
    {
        x=(x<<3) + (x<<1) + ch - '0';
        ch = getchar();
    }while(ch>='0'&&ch<='9');
    return f*x;
}

const int MAXN = 24 + 50;

int n,p;
long long C[MAXN][MAXN];
double dc[MAXN][MAXN];
long long dp1[MAXN][MAXN];
double dp2[MAXN][MAXN];

inline long long Pow(int a,int b)
{
    long  long res = 1 ,mul = a;
    while(b)
    {
        if(b & 1)
        {
            res *= mul;
            res %= p;
        }
        mul *= mul;
        mul %= p;
        b >>= 1;
    }
    return res;
}

inline double dfac(int x)
{
    if(x == 1||x == 0) return 1.0;
    else return 1.0 * x * dfac(x-1);
}

inline long long fac(int x)
{
    if(x == 1 ||x == 0) return 1;
    else return x * fac(x-1)%p;
}

int main()
{
    n = read(),p = read();
    for(int i=0;i<=n;i++)
    {
        C[i][0] = 1;dc[i][0] = 1;
        for(int j=1;j<=i;j++)
        {
            C[i][j] = (C[i-1][j] + C[i-1][j-1]) % p;
            dc[i][j] = dc[i-1][j] + dc[i-1][j-1];
        }
    }
    dp1[1][1] = dp1[2][2] = dp2[1][1] = dp2[2][2] = 1;
    for(int i=3;i<=n;i++)
    {
        for(int j=2;j<=i;j++)
        {
            for(int k=1;k<=i-2;k++)
            {
                for(int dep=1;dep<=min(j-2,k);dep++)
                {
                    dp1[i][j] = (dp1[i][j] + 1LL * dp1[k][dep] * dp1[i-k][j] % p * C[i-2][k-1] % p) % p;
                    dp2[i][j] = dp2[i][j] + dp2[k][dep] * dp2[i-k][j] * dc[i-2][k-1];
                }
            }
            for(int k=1;k<i;k++)
            {
                for(int dep=1;dep<=j;dep++)
                {
                    dp1[i][j] = (dp1[i][j] + 1LL * dp1[k][j-1] * dp1[i-k][dep] % p * C[i-2][k-1] % p) % p;
                    dp2[i][j] = (dp2[i][j] + dp2[k][j-1] * dp2[i-k][dep] * dc[i-2][k-1]);
                }
            }
        }
    }
    long long ans = 0;
    double dans = 0;
    for(int i=1;i<=n;i++)
    {
        ans = (ans + 1LL * i * dp1[n][i] % p) % p;
        dans = dans + i * dp2[n][i];
    }
    printf("%.0lf\n",round(dans/dfac(n-1)));
    printf("%lld\n",1LL * ans * Pow(fac(n-1),p-2) % p);
    return 0;
}

 

posted @ 2020-03-10 22:41  wlzs1432  阅读(367)  评论(0编辑  收藏  举报