bzoj1430 小猴打架 prufer编码

本文探讨了一群小猴子通过打架最终成为好友的所有可能过程数量。采用数学方法将问题转化为生成树的数量计算,利用prufer编码理论推导出具体公式,并提供了一段C语言代码实现解决方案。

Description


一开始森林里面有N只互不相识的小猴子,它们经常打架,但打架的双方都必须不是好朋友。每次打完架后,打架的双方以及它们的好朋友就会互相认识,成为好朋友。经过N-1次打架之后,整个森林的小猴都会成为好朋友。 现在的问题是,总共有多少种不同的打架过程。 比如当N=3时,就有{1-2,1-3}{1-2,2-3}{1-3,1-2}{1-3,2-3}{2-3,1-2}{2-3,1-3}六种不同的打架过程。

50%的数据N<=10^3。
100%的数据N<=10^6。
方案数mod 9999991。

Solution


结论题
N-1次打架之后形成连通图,实际上可以看做将N-1条边接入图中使其形成树,可以将树化为唯一对应的prufer编码,那么,树的个数实际就是prufer编码的的数目。
由转化prufer编码的方式可知,对于一棵N节点树来说,其prufer编码有N-2位,而生成树的个数就是prufer的个数。那么,就是N^(N-2)个,而加边顺序有(N-1)!种,根据乘法原理,则共有(N-1)!*(N^(N-2))个

Code


#include <stdio.h>
#include <string.h>
typedef long long ll;
const int MOD=9999991;
ll ksm(ll x,ll y) {
    ll ret=1;
    while (y) {
        if (y&1) ret=ret*x%MOD;
        x=x*x%MOD;
        y>>=1;
    }
    return ret;
}
int main(void) {
    int n; scanf("%d",&n);
    ll ans=ksm((ll)n,(ll)(n-2));
    for (ll i=1;i<n;i++) ans=ans*i%MOD;
    printf("%lld\n", ans);
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值