• P4492 [HAOI2018]苹果树


    思路

    题目要求的其实就是每种方案的权值之和(因为每种方案的概率相等)

    所以自然想到要求所有的边对最终答案的贡献次数

    考虑这一条边被经过了多少次,有这个子树内的点数*子树外的点数次,即(k imes(n-k))

    然后考虑总共的中序遍历总共有(n!)种,每种方案等概率

    先钦定一个点(i)(乘上(i!)),然后枚举它的(sz),这样相当于枚举了每种生成的树的形态,做到了不重不漏

    对于这个点(i),考虑选择K个点作为它的子树进行统计((sz_i=K+1)),然后选择的k个点的方案数是(left(egin{matrix}n-i\Kend{matrix} ight)),这(K)个点能构成的树的形态总数有(K!)个,然后考虑剩下的(n-k-i)个点的分配方案,因为不能放在(i)的子树中,所以分配的方案有((i-1)(i)dots(n-K-2))种((n-K-2)因为只剩一个点,能选择(n-sz_i-1=n-K-2)个点),化简一下等于(frac{(n-k-2)!}{(i-2)!})

    然后式子就出来了(注意i从二开始,因为从1开始似乎没有什么意义)

    [egin{align}ans=&sum_{i=2}^ni!sum_{j=1}^{n-i+1}j!left(egin{matrix}n-i\j-1end{matrix} ight)frac{(n-j-1)!}{(i-2)!}j(n-j)\=&sum_{i=2}^nsum_{j=1}^{n-i+1}j!left(egin{matrix}n-i\j-1end{matrix} ight)(n-j-1)!(i-1)ij(n-j)end{align} ]

    然后就很可做了

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define int long long
    using namespace std;
    int n,p,C[2010][2010],jc[2010],ans=0;
    signed main(){
        scanf("%d %d",&n,&p);
        jc[0]=1;
        for(int i=1;i<=n;i++)
            jc[i]=(jc[i-1]*i)%p;
        C[0][0]=1;
        for(int i=1;i<=n;i++)
            C[i][0]=C[i][i]=1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<i;j++)
                C[i][j]=(C[i-1][j-1]+C[i-1][j])%p;
        for(int i=2;i<=n;i++)
            for(int j=1;j<=n-i+1;j++)
                ans=(ans+jc[j]*C[n-i][j-1]%p*jc[n-j-1]%p*(i-1)%p*i%p*j%p*(n-j)%p+p)%p;
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    算法(一)—— 河内之塔(汉诺塔)
    JAVA爬取网页邮箱
    js中判断某字符串含有某字符出现的次数
    逻辑删除和物理删除的区别
    Forward和Redirect的区别
    Postman 传Map类型的参数
    Java基础
    【html-css】
    【HTML----】
    【python-while-以及字符串的相关操作和函数】
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10554445.html
Copyright © 2020-2023  润新知