BZOJ5305 HAOI2018 苹果树

本文深入探讨了一个涉及二叉树节点排列组合的复杂问题,通过细致的数学分析和算法设计,提出了一种有效的解决方案。核心在于利用组合数学原理,结合递归思想,巧妙地计算了不同规模下二叉树所有可能的形态及其节点间的连接方式。
摘要由CSDN通过智能技术生成

好题qwq

写起来不到1k很舒服

自己对期望与计数的能力还是差一点

我们观察这个题 首先我们发现有一个*n!

这个是怎么一回事呢

是因为每添一个节点就会少1个位置但又多出2个位置所以每一次添加的可选位置数就是i

然后呢我们观察这个题有一些很好的性质 比如二叉树

首先根据常见套路我们可以计算一条边的贡献是szi*(n-szi)

那么我们只需要讨论到底有多少边接的节点是szi即可

我们观察到n只有2000 提示我们可以n^2

于是我们可以枚举一个x 再枚举一个x的sz

也就是说再x后面要有sz-1个点选择长在x的子树里 又因为这个子树里面父亲必须比儿子小 所以跟题目描述的生成方式是一样的

这个贡献是C(n-x,sz-1)*sz!

我们继续考虑子树外面的 一共有n-sz个节点 先考虑x以前的节点 一共是x!种生成方式

再考虑x以后的其它节点 一共有(n-x-sz+1)个都不能长到x的里面就是(x+1-2)*(x+2-2)*(n-sz+1-2)种生成方式

上面两个合并一下就是(n-sz-1)!i(i-1)

所以我们就做完啦

最后的贡献式就是把上面乘起来再相加

$\sum_{x=2}^n\sum_{sz=1}^{n-x+1}(n-sz-1)!i(i-1)sz!C(n-x,sz-1)sz(n-sz)$

一步一步推就能推出来哒

由于取模没保证素数所以我们按照杨辉三角求C然后阶乘正常求就可以了qwq

//Love and Freedom.
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 20021225
#define N 2001
using namespace std;

int C[N][N],fac[N],n,m;
void pre()
{
    C[0][0]=C[1][0]=C[1][1]=1; fac[1]=fac[0]=1;
    for(int i=2;i<=n;i++)
    {
        fac[i]=1ll*fac[i-1]*i%m; C[i][0]=C[i][i]=1;
        for(int j=1;j<n;j++)
            C[i][j]=(C[i-1][j-1]+C[i-1][j])%m;
    }
}
int main()
{
    scanf("%d%d",&n,&m); pre(); int ans=0;
    for(int x=2;x<=n;x++)    for(int sz=1;sz<=n-x+1;sz++)
    {
        int tmp=1ll*fac[sz]*C[n-x][sz-1]%m*x%m*(x-1)%m*fac[n-sz-1]%m*sz%m*(n-sz)%m;
        ans=(ans+tmp)%m;
    } 
    printf("%d\n",ans);
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/hanyuweining/p/11106561.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值