• [BZOJ1211]:[HNOI2004]树的计数(prufer序列)


    题目传送门


    题目描述

    一个有n个结点的树,设它的结点分别为$v_1,v_2,…,v_n$,已知第i个结点$v_i$的度数为$d_i$,问满足这样的条件的不同的树有多少棵。给定n,$d_1,d_2,…,d_n$,编程需要输出满足$d_{v_i} = d_i$的树的个数。


    输入格式

    第一行是一个正整数n,表示树有n个结点。第二行有n个数,第i个数表示$d_i$,即树的第i个结点的度数。


    输出格式

    输出满足条件的树有多少棵。


    样例

    样例输入

    4
    2 1 2 1

    样例输出

    2


    数据范围与提示

    $1 leqslant n leqslant 150$。

    输入数据保证满足条件的树不超过${10}^{17}$个。


    题解

    显然是一道prufer序列的板子题,确定n个点度数分别是为$d_1,d_2,...$时无根树个数:$frac{(n-2)!}{(d_1-1)! imes (d_2-1)! imes ...}$

    但是需要注意两个特判:

      1.要满足是一棵树则$sum limits_{i=1}^{n}d_i=2 imes n-2$。

      2.当$n=1$时显然不方便处理,则直接输出1即可。

    直接输出“0”你会惊喜的发现,你有15分!

    至于实现过程,可以使用高精暴力求,当然也可以使用分解质因数,显然后者更好实现。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    int d[151];
    int pre[400],pri[400];
    long long wzc[400];
    long long ans=1LL;
    void pre_work()//预处理质因数
    {
    	for(int i=2;i<=2*n;i++)
    	{
    		if(!pri[i])
    		{
    			pri[i]=i;
    			pre[++pre[0]]=i;
    		}
    		for(int j=1;j<=pre[0];j++)
    		{
    			if(pre[j]>pri[i]||i*pre[j]>n)break;
    			pri[i*pre[j]]=pre[j];
    		}
    	}
    }
    long long qsm(long long x,long long y)
    {
    	long long rec=1;
    	while(y)
    	{
    		if(y&1)rec*=x;
    		x*=x;
    		y>>=1;
    	}
    	return rec;
    }
    int main()
    {
    	scanf("%d",&n);
    	pre_work();
    	int sum=0;
    	bool flag=0;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&d[i]);
    		if(!d[i])flag=1;
    		sum+=d[i];
    	}
    	if(n==1&&!d[1]){puts("1");return 0;}
    	if(sum!=2*n-2||flag){puts("0");return 0;}//两个特判
    	for(int i=1;i<=n-2;i++)
    	{
    		int flag=i;
    		while(flag>1)
    		{
    			wzc[pri[flag]]++;
    			flag/=pri[flag];
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<d[i];j++)
    		{
    			int flag=j;
    			while(flag>1)
    			{
    				wzc[pri[flag]]--;
    				flag/=pri[flag];
    			}
    		}
    	}
    	for(int i=1;i<=n;i++)
    		if(wzc[i])ans=ans*qsm(i,wzc[i]);//计算答案
    	printf("%lld",ans);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    http协议详谈
    配置nginx 反向代理
    利用background-positon,background-image ,实现背景渐变
    vue +webpack 打包配置优化
    记项目中易出现的bug点
    vue 中基于html5 drag drap的拖放
    vue 项目技巧
    完整项目搭建全过程(vue-cli+webpack)
    vue+ D3+drag
    项目总结(3.28)
  • 原文地址:https://www.cnblogs.com/wzc521/p/11222183.html
Copyright © 2020-2023  润新知