bzoj 5346: tree (其实是是某次雅礼集训的题)

 

   用prufer序列的公式直接dp,O(n^4)的算法简简单单就写出来了23333.

    按理说 O(n^4)是需要优化成O(n^3)才能过的,然鹅我也不知道我怎么过了23333

(那就懒得优化了hhhhh)

 

(后来翻了翻std,发现标算就是O(n^4)的。。。。迷)

 

/*
    f[i][j] -> 已经选了i个节点,度数和为j 的∑( π1/(degree[i]-1)!)  
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int maxn=105,ha=1004535809;
int f[maxn][maxn*2],n,d[maxn],jc[maxn],ni[maxn],M;

inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}
inline void ADD(int &x,int y){ x+=y; if(x>=ha) x-=ha;}

inline int ksm(int x,int y){
	int an=1;
	for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;
	return an;
}

inline void init(){
	jc[0]=1;
	for(int i=1;i<=100;i++) jc[i]=jc[i-1]*(ll)i%ha;
	ni[100]=ksm(jc[100],ha-2);
	for(int i=100;i;i--) ni[i-1]=ni[i]*(ll)i%ha;
}

inline void solve(){
	f[0][0]=1;
	for(int i=1;i<=n;i++)
	    for(int j=i-1;j>=0;j--)
	        for(int k=M;k>=0;k--) if(f[j][k])
	            for(int u=min(d[i],M-k);u;u--) ADD(f[j+1][k+u],f[j][k]*(ll)ni[u-1]%ha);
}

inline void calc(){
	printf("%d ",n);
	for(int i=2;i<=n;i++) printf("%d ",f[i][(i-1)<<1]*(ll)jc[i-2]%ha);
	puts("");
}

int main(){
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	
	init();
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",d+i),d[i]=min(d[i],n-1);
	M=n*2-2,solve(),calc();
	
	return 0;
}

  

posted @ 2018-05-24 19:29  蒟蒻JHY  阅读(306)  评论(0编辑  收藏  举报