题面

有n个点,它们从1到n进行标号,第i个点的限制为度数不能超过A[i].

现在对于每个s (1 <= s <= n),问从这n个点中选出一些点组成大小为s的有标号无根树的方案数。

100%的数据:n <= 100

100

prufer序列

每个大小为n,有标号无根树都可以表示成一个长度为(n-2)且取值在[1,n]的序列。

这个序列就叫prufer序列

树转prufer序列

1.每次查找一个标号最小且度数为一的点,使与之相连的点的编号加入序列尾;

2.删除树中的这个点。

prufer序列转树

1.新建一个包含[1,n]的集合;

2.找出集合中在序列中未出现的最小编号,并使之与序列头连一条边;

3.删除集合中的这个编号,以及序列头;

4.重复2-3步骤n-2次,序列则为空;

5.把集合中的剩余两个编号相连,原树复原。

性质

1.长度为(n-2)的prufer序列的集合与大小为n的带标号无根树的集合一一映射。

2.带标号无根树的任意点的度数等于,与之对应的prufer序列的对应编号出现次数+1。


Back to Problem

Pre

假设我们求出了一个prufer序列的长度\(n\),并且知道其中每个编号出现的次数\(c_i\)。

由性质2,那么这种prufer序列的贡献就是,它的不同全排列数,有:

\[Ans=n!*\sum_{i=1}^n\frac{1}{c_i!}
\]

正文

所以我们把原题转化为在序列上的动态规划

设\(f_{i,j,k}\)表示前i个点,用了j个点,序列长度为k的方案数。

那么就有,

\[f_{i,j,k} \Rightarrow \begin{cases}
f_{i+1,j,k}\\
f_{i+1,j+1,k+l},&l \in [0,a_i-1]
\end{cases}
\]

最终答案就是\(f_{n,s,s-2}*(s-2)!\)。

时间复杂度为\(O(n^4)\),但由于冗余状态的存在,是能卡过的。

原题是要用FFT优化到\(O(n^3*log_n)\)

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define ll long long
#define fo(i,x,y) for(int i=x;i<=y;i++)
#define fd(i,x,y) for(int i=x;i>=y;i--)
using namespace std;
const char* fin="tree.in";
const char* fout="tree.out";
const int inf=0x7fffffff;
const int maxn=107,mo=1004535809;
int n,a[maxn],f[maxn][maxn][maxn],fact[maxn],nf[maxn];
int qpower(int a,int b){
int c=1;
while (b){
if (b&1) c=1LL*a*c%mo;
a=1LL*a*a%mo;
b>>=1;
}
return c;
}
int ni(int v){return qpower(v,mo-2);}
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
scanf("%d",&n);
fact[0]=1;
fo(i,1,maxn-1) fact[i]=1LL*fact[i-1]*i%mo;
fo(i,0,maxn-1) nf[i]=ni(fact[i]);
fo(i,1,n) scanf("%d",&a[i]);
memset(f,0,sizeof f);
f[1][0][0]=1;
fo(i,1,n)
fo(j,0,i-1)
fo(k,0,n){
f[i+1][j][k]=(f[i][j][k]+f[i+1][j][k])%mo;
fo(l,0,a[i]-1){
if (k+l>n) break;
f[i+1][j+1][k+l]=(f[i+1][j+1][k+l]+1LL*f[i][j][k]*nf[l])%mo;
}
}
printf("%d ",n);
fo(i,2,n) cout<<1LL*f[n+1][i][i-2]*fact[i-2]%mo<<" ";
return 0;
}

【JZOJ5068】【GDSOI2017第二轮模拟】树 动态规划+prufer序列的更多相关文章

  1. 【JZOJ5071】【GDSOI2017第二轮模拟】奶酪 树形dp

    题面 CJY很喜欢吃奶酪,于是YJC弄到了一些奶酪,现在YJC决定和CJY分享奶酪. YJC弄到了n-1块奶酪,于是他把奶酪挂在了一棵n个结点的树上,每根树枝上挂一块奶酪,每块奶酪都有重量. YJC和 ...

  2. 【JZOJ5060】【GDOI2017第二轮模拟day1】公路建设 线段树+最小生成树

    题面 在Byteland一共有n 个城市,编号依次为1 到n,它们之间计划修建m条双向道路,其中修建第i 条道路的费用为ci. Byteasar作为Byteland 公路建设项目的总工程师,他决定选定 ...

  3. [jzoj5073 GDOI2017第二轮模拟] 影魔

    Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵 ...

  4. 【JZOJ5064】【GDOI2017第二轮模拟day2】友好城市 Kosarajo算法+bitset+ST表+分块

    题面 在Byteland 一共有n 座城市,编号依次为1 到n,这些城市之间通过m 条单向公路连接. 对于两座不同的城市a 和b,如果a 能通过这些单向道路直接或间接到达b,且b 也能如此到达a,那么 ...

  5. GDOI2017第二轮模拟day1 总结

    平民比赛 这场比赛的暴力分非常友好. 但是我并没有拿到全部的暴力分. 1(暴力分\(60/100\)) 暂时我可以拿的暴力分为\(30/100\),直接mst模拟即可. 然而当时打了个辣鸡莫队,结果爆 ...

  6. bzoj 1005: [HNOI2008]明明的烦恼 树的prufer序列+万进制

    题目传送门 思路: 这道题需要前置知识prufer编码,这篇博客对prufer编码和这道题的分析写的很好. 这里主要讲一些对大数阶乘的分解,一个办法当然是用高精度,上面这篇博客用的是java,还有一个 ...

  7. 树的Prufer 编码和最小生成树计数

      Prufer数列 Prufer数列是无根树的一种数列.在组合数学中,Prufer数列由有一个对于顶点标过号的树转化来的数列,点数为n的树转化来的Prufer数列长度为n-2.它可以通过简单的迭代方 ...

  8. 【BZOJ 1211】 1211: [HNOI2004]树的计数 (prufer序列、计数)

    1211: [HNOI2004]树的计数 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2468  Solved: 868 Description 一 ...

  9. bzoj1211: [HNOI2004]树的计数(prufer序列+组合数学)

    1211: [HNOI2004]树的计数 题目:传送门 题解: 今天刚学prufer序列,先打几道简单题 首先我们知道prufer序列和一颗无根树是一一对应的,那么对于任意一个节点,假设这个节点的度数 ...

随机推荐

  1. Django之模板语言(四) ------>Tags

    案例1:单层for循环 # Django 模板语言测试代码 def template_test(request): name_list=["张三","李四",& ...

  2. Android笔记之让Debug和Release模式使用相同的签名

    方法如下图 完整的build.gradle如下 apply plugin: 'com.android.application' android { compileSdkVersion 29 build ...

  3. C# 把十六进制表示的ASCII码转换为对应的字符组成的字符串

    0x30表示字符‘0’的ASCII码.

  4. oracle中准确控制job的下次运行时间(next date)

    用过ORACLE的JOB的朋友也许都能够感觉到它的强大,和JAVA中的quartz有异曲同工之妙,可以少了很多的重复劳动:但是也会有许多问题,就是执行时间段和执行时间比较不容易确定. 这其实都是我们还 ...

  5. 跟我一起在ubuntu中安装docker

    卸载旧版本 $ sudo apt-get remove docker docker-engine docker.io 查看ubuntu版本 设置安装源 通过如下步骤,设置安装源仓库,这里我们使用阿里源 ...

  6. thinkphp+ajax 实现点击加载更多数据

    https://blog.csdn.net/a898712940/article/details/78545599?utm_source=blogxgwz8 适用范围:thinkphp3.2和thin ...

  7. 深入浅出 Java Concurrency (5): 原子操作 part 4[转]

    在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁(后面的章节还会谈到锁). 锁机制存在以下问题: (1)在多线程竞争下,加锁.释放锁会导致比较多的上下文切换和调度 ...

  8. Delphi 设计模式:《HeadFirst设计模式》Delphi2007代码---工厂模式之工厂方法[转]

      1   2{<HeadFirst设计模式>工厂模式之工厂方法 }   3{ 产品类                              }   4{ 编译工具 :Delphi20 ...

  9. 原生 js 实现摇一摇功能

    参考此大牛的博客:https://blog.csdn.net/chclvzxx/article/details/46325053

  10. name和value的简单js用法

    name和value: 例如: <input type="text" name="txt"/> name用于定义这个input收到的值的变量名,在上 ...