luogu P2290 [HNOI2004]树的计数

Posted 275307894a

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P2290 [HNOI2004]树的计数相关的知识,希望对你有一定的参考价值。

题面传送门
首先这种生成树计数想到Prufer序列。
然后因为度数为\\(d_i\\)的点会在Prufer序列中出现\\(d_i-1\\)次所以直接重排列公式即可。
然而这个没有模数什么的。
于是就要分解完质因数后再乘。
时间复杂度\\(O(nlogn)\\)
code:

#include <vector>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#include<bitset>
#include<set>
#include<map>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 150
#define M 100000
#define eps (1e-5)
#define mod (1<<31)
#define U unsigned int
using namespace std;
int n,x,A[N+5],G[N+5],fl[N+5],pre[N+5],pr[N+5],ph,ToT; ll Ans=1;
int main(){
	freopen("1.in","r",stdin);
	re int i,j;scanf("%d",&n);if(n==1){scanf("%d",&x);printf("%d\\n",x?0:1);return 0;}
	A[n-2]++;for(i=2;i<=n;i++){
		!fl[i]&&(pr[++ph]=i,pre[i]=i);for(j=1;j<=ph&&pr[j]*i<=n;j++){fl[pr[j]*i]=1;pre[pr[j]*i]=pr[j];if(i%pr[j]==0) break;}
	}
	for(i=1;i<=n;i++){scanf("%d",&x),A[x-1]--,ToT+=x;if(!x){printf("0\\n");return 0;}}if(ToT!=2*n-2){printf("0\\n");return 0;}
	for(i=n;i;i--) A[i]+=A[i+1];
	for(i=1;i<=n;i++){x=i;while(x^1)G[pre[x]]+=A[i],x/=pre[x];}
	for(i=1;i<=n;i++) while(G[i]--) Ans*=i;printf("%d\\n",Ans);
}

以上是关于luogu P2290 [HNOI2004]树的计数的主要内容,如果未能解决你的问题,请参考以下文章

[luogu P2292] [HNOI2004]L语言

luogu P1437 [HNOI2004]敲砖块

luogu P2285 [HNOI2004]打鼹鼠

bzoj 1211 [HNOI2004]树的计数

bzoj1211: [HNOI2004]树的计数

题解Luogu p2285 BZOJ1207 [HNOI2004]打鼹鼠