BZOJ 1005: [HNOI2008]明明的烦恼

本文介绍如何使用Prüfer序列计算特定条件下树的可能构造方式数目,通过组合数学的方法,详细解析了确定度数节点和不确定度数节点在序列中的位置选择及其方案数的计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

prufer序列

因为每个prufer序列唯一对应一颗树,所以如果能求出prufer序列的方案数就能求出树的方案数

一颗 n 个节点的树的prufer序列有 n-2 个数字,每个数字在 [1,n] 的范围内,表示节点编号

对应一个度数为 $d_i$ 的点,它会在prufer序列中出现 $d_i-1$ 次

设 m 为度数确定的节点数量,$d_i$ 为某个节点的度数

设 $sum=\sum _{i=1}^{m}(d_i-1)$

那么已经确定的节点在 prufer 序列中占据了 sum 个位置

这 sum 的位置在 n-2 个位置中放置的方案数显然为 $C^{sum}_{n-2}$

然后单独考虑这个长度为 sum 的序列的情况

对于确定度数的节点 1,它要在长度为 sum 的序列中选 $d_1-1$ 个位置

有 $C^{d_1-1}_{sum}$ 种方案

对于第 2 个节点,因为节点 1 先选好了,所以它要在长度为 $sum-(d_1-1)$ 的序列中选 $d_2-1$ 个位置

有 $C^{d_2-1}_{sum-(d_1-1)}$ 种方案

这样推广下去,用乘法原理把所有的 C 乘起来(化简过程自己推一下)

最后得到 $C^{sum}_{n-2}\frac{sum!}{\prod ^{m}_{i=1}(d_i-1)}$

然后考虑不确定的点,剩下 n-2-sum 个位置顺便填剩下 n-m 个数

有 $(n-m)^{(n-2-sum)}$ 种方案

最后一起乘起来就好了

答案要高精度,但是因为最后答案一定是整数,所以可以提出分子分母的质因数化简分式,不用高精除

高精怕麻烦没写压位

别忘了判断无解

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=20007;
int n,d[N],m,sum;
int pri[N],tot,f[N];//f[i]表示i最小的质因数
bool not_pri[N];
void pre()//欧拉筛求每个数最小的质因数
{
    not_pri[1]=1; f[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!not_pri[i]) { pri[++tot]=i; f[i]=i; }//质数的最小质因数就是本身
        for(int j=1;j<=tot;j++)
        {
            int g=i*pri[j]; if(g>n) break;
            not_pri[g]=1; f[g]=pri[j];
            if(i%pri[j]==0) break;
        }
    }
}
int cnt[N];//cnt存每个质因数出现的次数
inline void work(int x,bool p)//p表示此时化简的是分子还是分母
{
    if(p) while(x!=1) cnt[f[x]]++,x/=f[x];
    else while(x!=1) cnt[f[x]]--,x/=f[x];
}
struct BIGINT//高精度存答案
{
    int a[N],len;
    BIGINT() { memset(a,0,sizeof(a)); len=1; }
    inline void mul(int tmp)//高精乘低精
    {
        for(int i=1;i<=len;i++) a[i]*=tmp;
        for(int i=1;i<=len;i++)
        {
            a[i+1]+=a[i]/10;
            a[i]%=10;
        }
        while(a[len+1]) len++,a[len+1]+=a[len]/10,a[len]%=10;
    }
    inline void print() { for(int i=len;i;i--) printf("%d",a[i]); }//输出
};
int main()
{
    int a;
    n=read(); pre();
    for(int i=1;i<=n;i++)
    {
        a=read(); if(a==-1) continue;
        if(!a) { printf("0"); return 0; }//判断无解
        d[++m]=a; sum+=a-1;
    }
    if(sum>2*n-2) { printf("0"); return 0; }//判断无解
    for(int i=n-1-sum;i<=n-2;i++) work(i,1);
    for(int i=1;i<=m;i++)
        for(int j=2;j<=d[i]-1;j++) work(j,0);
    for(int i=1;i<=n-2-sum;i++) work(n-m,1);
    BIGINT ans; ans.a[1]=1;
    for(int i=2;i<=n;i++)
        for(int j=1;j<=cnt[i];j++)
            ans.mul(i);
    ans.print();
    return 0;
}

 

转载于:https://www.cnblogs.com/LLTYYC/p/10104542.html

内容概要:本文系统介绍了基于C#(VS2022+.NET Core)与HALCON 24.11的工业视觉测量拟合技术,涵盖边缘提取、几何拟合、精度优化及工业部署全流程。文中详细解析了亚像素边缘提取、Tukey抗噪算法、SVD平面拟合等核心技术,并提供了汽车零件孔径测量、PCB焊点共面性检测等典型应用场景的完整代码示例。通过GPU加速、EtherCAT同步等优化策略,实现了±0.01mm级测量精度,满足ISO 1101标准。此外,文章还探讨了深度学习、量子启发式算法等前沿技术的应用前景。 适合人群:具备一定编程基础,尤其是熟悉C#和HALCON的工程师或研究人员,以及从事工业视觉测量与自动化检测领域的技术人员。 使用场景及目标:①学习如何使用C#和HALCON实现高精度工业视觉测量系统的开发;②掌握边缘提取、抗差拟合、3D点云处理等核心技术的具体实现方法;③了解工业部署中的关键技术,如GPU加速、EtherCAT同步控制、实时数据看板等;④探索基于深度学习和量子计算的前沿技术在工业视觉中的应用。 其他说明:本文不仅提供了详细的理论分析和技术实现,还附有完整的代码示例和实验数据,帮助读者更好地理解和实践。同时,文中提到的硬件选型、校准方法、精度验证等内容,为实际项目实施提供了重要参考。文章最后还给出了未来的技术演进方向和开发者行动建议,如量子-经典混合计算、自监督学习等,以及参与HALCON官方认证和开源社区的建议。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值