树的计数(prufer序列 或 purfer序列)
题解
首先我们要知道一条性质,prufer序列中的某个点出现次数为该点在树中度数-1
感性理解一下,其实按照prufer序列求法自己推一下就出来了
设题目里给的度为$d[]$
先将所有的d--
然后按照排列组合得出来
这是多重集排列数
首先从n-2中选择d[1]个数是$C_{n}^{d[1]}$然后再从剩余n-d[1]中选d[2] $C_{n-d[1]}^{d[2]}$依次类推
$C_{n-2}^{d[1]}\times C_{n-2-d[1]}^{d[2]}\times C_{n-2-d[1]-d[2]}^{d[3]}\times ……\times C_{n-2-d[1]-……-d[n-1]}^{d[n]}$
得到
$\frac{(n-2)!}{\sum\limits_{i=1}^{n}d[i]!}$
高精转移就完了
还是过不了?
一些特判:
首先该题会有无解的情况
然后当只有一个点时方案数为1
然后当出现度数为0的点时方案数要特殊处理
以下是本人丑陋的代码
- #include<bits/stdc++.h>
- #define ll long long
- #define N 10
- #define P 1
- using namespace std;
- ll n,m,d[20000],cnt=0;
- bool flag[20000];
- struct bignum
- {
- ll n[200000],l;
- bignum(){l=1,memset(n,0,sizeof(n));}
- void clear(){while(l>1&&!n[l-1]) l--;}
- void print()
- {
- printf("%lld",n[l-1]);
- for(ll i=l-2;i>=0;i--)
- printf("%0*lld",P,n[i]);
- printf("\n");
- }
- bignum operator = (ll x)
- {
- l=0;
- while(x)
- {
- n[l++]=x%N;
- x/=N;
- }
- return *this;
- }
- bignum operator +(bignum x) const
- {
- bignum t=*this;
- if(x.l>t.l) t.l=x.l;
- for(ll i=0;i<t.l;i++)
- {
- t.n[i]+=x.n[i];
- if(t.n[i]>=N)
- {
- t.n[i+1]+=t.n[i]/N;
- t.n[i]%=N;
- }
- }
- return t;
- }
- bignum operator * (const ll& b)
- {
- bignum c;
- c.l=0;
- for(ll i=0,g=0;g||i<l;i++)
- {
- ll x;
- if(i<l)x=n[i]*b+g;
- else x=g;
- c.n[c.l++]=x%N;
- g=x/N;
- }
- return c;
- }
- bignum operator *(bignum x) const
- {
- bignum t=*this,tep;
- tep.l=t.l+x.l+1;
- for(ll i=0;i<t.l;i++)
- for(ll j=0;j<=x.l;j++)
- {
- tep.n[i+j]+=t.n[i]*x.n[j];
- }
- for(ll i=0;i<tep.l;i++)
- {
- tep.n[i+1]+=tep.n[i]/N;
- tep.n[i]%=N;
- }
- tep.clear();
- return tep;
- }
- bool operator <(bignum x) const
- {
- bignum t=*this,tep;
- if(t.l!=x.l) return t.l<x.l;
- for(ll i=t.l-1;i>=0;i--)
- {
- if(t.n[i]!=x.n[i]) return t.n[i]<x.n[i];
- }
- return 0;
- }
- bool operator >(bignum x) const
- {
- bignum t=*this;
- if(t.l!=x.l) return t.l>x.l;
- for(ll i=t.l-1;i>=0;i--)
- {
- if(t.n[i]!=x.n[i]) return t.n[i]>x.n[i];
- }
- return 0;
- }
- bignum operator -(bignum x) const
- {
- bignum t=*this;
- if(t<x) printf("-"),swap(t,x);
- ll jie=0;
- for(ll i=0;i<t.l;i++)
- {
- t.n[i]-=x.n[i];
- while(t.n[i]<0)
- {
- t.n[i]+=N;
- jie++;
- }
- t.n[i+1]-=jie;
- jie=0;;
- }
- t.clear();
- return t;
- }
- bignum operator /(const ll &x)
- {
- bignum t=*this,r;
- ll tmp=0;
- r.l=t.l;
- for(ll i=t.l-1;i>=0;i--){
- tmp+=t.n[i];
- if(tmp>=x){
- r.n[i]=tmp/x;
- tmp%=x;
- }
- tmp*=N;
- }
- r.clear();
- return r;
- }
- }ans;
- bignum jie(ll x)
- {
- bignum t;t=1;
- for(ll i=2;i<=x;i++){
- t=x*i;
- }
- return t;
- }
- int main()
- {
- memset(flag,0,sizeof(flag));
- ll sum=0,you0=0;
- scanf("%lld",&n);
- for(ll i=1;i<=n;i++)
- {
- scanf("%lld",&d[i]);
- if(d[i])flag[i]=1,cnt++;
- else you0=1;
- d[i]--,sum+=d[i];
- }
- if(you0&&n==1){
- cout<<1<<endl;
- return 0;
- }
- if(sum!=n-2||you0)
- {
- cout<<0<<endl;
- return 0;
- }
- ans=1;
- for(ll i=2;i<=cnt-2;i++)
- ans=ans*i;
- for(ll i=1;i<=n;i++){
- if(flag[i])
- for(ll j=2;j<=d[i];j++)
- ans=ans/j;
- }
- ans.print();
- }
树的计数(prufer序列 或 purfer序列)的更多相关文章
- 树的计数 + prufer序列与Cayley公式(转载)
原文出处:https://www.cnblogs.com/dirge/p/5503289.html 树的计数 + prufer序列与Cayley公式 学习笔记(转载) 首先是 Martrix67 的博 ...
- 树的计数 + prufer序列与Cayley公式 学习笔记
首先是 Martrix67 的博文:http://www.matrix67.com/blog/archives/682 然后是morejarphone同学的博文:http://blog.csdn.ne ...
- Luogu P2290 [HNOI2004]树的计数 Prufer序列+组合数
最近碰了$prufer$ 序列和组合数..于是老师留了一道题:P2624 [HNOI2008]明明的烦恼 qwq要用高精... 于是我们有了弱化版:P2290 [HNOI2004]树的计数(考一样的可 ...
- 树的计数 Prufer序列+Cayley公式
先安利一发.让我秒懂.. 第一次讲这个是在寒假...然而当时秦神太巨了导致我这个蒟蒻自闭+颓废...早就忘了这个东西了... 结果今天老师留的题中有两道这种的:Luogu P4981 P4430 然后 ...
- [HNOI2004]树的计数 prufer数列
题面: 一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, …, dn,你的程序需要输出满足d( ...
- bzoj1211: [HNOI2004]树的计数 prufer编码
题目链接 bzoj1211: [HNOI2004]树的计数 题解 prufer序 可重排列计数 代码 #include<bits/stdc++.h> using namespace std ...
- BZOJ 1211 HNOI2004 树的计数 Prufer序列
题目大意:给定一棵树中全部点的度数,求有多少种可能的树 Prufer序列.详细參考[HNOI2008]明明的烦恼 直接乘会爆long long,所以先把每一个数分解质因数.把质因数的次数相加相减.然后 ...
- 【BZOJ1005/1211】[HNOI2008]明明的烦恼/[HNOI2004]树的计数 Prufer序列+高精度
[BZOJ1005][HNOI2008]明明的烦恼 Description 自从明明学了树的结构,就对奇怪的树产生了兴趣......给出标号为1到N的点,以及某些点最终的度数,允许在任意两点间连线,可 ...
- 【BZOJ1211】【HNOI2004】树的计数 prufer序列
题目描述 给你\(n\)和\(n\)个点的度数,问你有多少个满足度数要求的生成树. 无解输出\(0\).保证答案不超过\({10}^{17}\). \(n\leq 150\) 题解 考虑prufer序 ...
随机推荐
- 2021/5/11 docker的应用
很快一天过去了,今天虽然没有加班,但是依旧感觉疲惫,弄了一天的docker镜像的问题.作为一名前端开发工程师从以前从未听说过docker到现在懂得了如何运用,也是不容易啊.之前也说过,我们项目结构是前 ...
- 『政善治』Postman工具 — 8、Postman中Pre-request Script的使用
目录 1.Pre-request Script介绍 2.常用SNIPPETS(片段)说明 (1)获取变量脚本: (2)设置变量脚本: (3)清空变量脚本: (4)Send a request代码片段 ...
- 成功的多项目管理都有哪些"制胜之道"?
实施多项目管理,一个重要原因就是提高项目的效率和管理水平.除了满足时间.成本.业绩和客户需求之外,项目管理办公室(PMO)经理的预期产出还包括有效利用组织资源.下面是影响多项目管理成功的几个关键因素, ...
- golang:面向对象总结
所谓的面向对象其实就是找一个专门做这个事的人来做,不用关心具体怎么实现的.所以说,面向过程强调的是过程,步骤.而面向对象强调的是对象,也就是干事的人. Go语言:面向对象语言特性 方法 嵌入 接口 没 ...
- [bug] maven“1.5不支持diamond运算符,请使用source 7或更高版本以启用diamond运算符”
原因 maven打包默认采用jdk 1.5,无法识别<> 解决 在pom.xml中加入: <properties> <maven.compiler.source>1 ...
- [Linux]常用命令、组合命令以及输入输出重定向
[Linux]常用命令.组合命令以及输入输出重定向 2020-03-10阅读 1580 原创文章 文章目录 0.切换目录 1.复制文件和目录`cp` 1.1.复制文件 1.2.复制目录 1.3.扩 ...
- Linux巡检常用命令
# uname -a # 查看内核/操作系统/CPU信息 # head -n 1 /etc/issue # 查看操作系统版本 # cat /proc/cpuinfo # 查看CPU信息 # hostn ...
- IT菜鸟之虚拟机VMware的安装
老师说过,如果想学好Linux,最好不要在实体机上安装Linux,因为学习需要经常折腾,在实体机上做实验,出现故障就要重新安装,这样绝大多数时间都会浪费在安装上. 这时我们需要一个工具,它就是虚拟机. ...
- Linux中级之ansible概念及hoc命令行调用模式
一.Ansible简介 ansible是新出现的开源的自动化运维工具,基于Python开发,集合了众多运维工具(puppet.cfengine.chef.func.fabric)的优点,实现了批量系统 ...
- shell基础之后台运行脚本
使shell脚本后台执行,基本的方法有两种,第一种为在脚本后面追加&符号,第二种为在脚本前面使用nohup命令,结尾再追加&符号 一.后台运行脚本1 1.执行脚本test.sh:./t ...