【洛谷P2290】樹的計數
阿新 • • 發佈:2021-01-21
題目
題目連結:https://www.luogu.com.cn/problem/P2290
一個有 \(n\) 個節點的樹,設它的節點分別為 \(v_1,v_2,\ldots,v_n\),已知第 \(i\) 個節點 \(v_i\) 的度數為 \(d_i\),問滿足這樣的條件的不同的樹有多少棵。
\(1\le n\le 150\),保證滿足條件的樹不超過 \(10^{17}\) 個。
思路
既然點有了度數限制,那麼等價於 prufer 序列上這個點出現次數必須是 \(\mathrm{deg}_i-1\)。
問題轉化為一個長度為 \(n-2\) 的序列,\(i\) 出現次數為 \(\mathrm{deg}_i-1\)
由於題目保證了答案不超過 long long 範圍,那麼直接分解質因數最後再乘起來即可。
時間複雜度 \(O(n^2)\)。
程式碼
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=155; int n,deg[N],cnt[N][N],a[N]; ll ans; int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { int p=i; for (int j=2;j<=n;j++) { cnt[i][j]=cnt[i-1][j]; for (;p%j==0;p/=j) cnt[i][j]++; } } for (int j=1;j<=n;j++) a[j]+=cnt[n-2][j]; for (int i=1;i<=n;i++) { scanf("%d",°[i]); if (!deg[i]) return printf("%d",deg[1]==0),0; for (int j=1;j<=n;j++) a[j]-=cnt[deg[i]-1][j]; deg[0]+=deg[i]-1; } if (deg[0]!=n-2) return printf("0"),0; ans=1; for (int i=1;i<=n;i++) for (;a[i];a[i]--) ans*=i; printf("%lld",ans); return 0; }