1. 程式人生 > >【BZOJ 1211】 [HNOI2004]樹的計數

【BZOJ 1211】 [HNOI2004]樹的計數

空格 就是 i+1 code uri ble Go 題意 php

【鏈接】 我是鏈接,點我呀:)
【題意】


在這裏輸入題意

【題解】


prufer數列的應用
http://www.cnblogs.com/AWCXV/p/7626625.html
這一題沒有節點的度數不定。
因此。
所有節點的度數-1的和結果一定要是n-2.
否則就無解。

然後把tot代成n-2就好了。
做法就一樣了。
(大體思路就是,從n-2個空格裏面選出d[i]個空格放節點i,從n-2-d[i]個空格裏面選出d[i+1]個空格放節點i+1
(化簡一下就成為上文中的式子了。
(d[i]==0的時候在n==1的時候是有解的
(可以不用高精度了這題
(結論,n!質因數分解後每個質因數p的指數為∑n/i 其中i為i,i^2,i^3...i^x 其中i^x<=n

【代碼】

#include <bits/stdc++.h>
using namespace std;

const int N = 150;

int n,d[N+10],cnt[N+10];
bool is[N+10];

bool ok(int n){
    int len = sqrt(n);
    for (int i = 2;i <= len;i++)
        if (n%i==0)
            return false;
    return true;
}

void go(int n,int delta){
    for (int i = 1
;i <= n;i++){ if (is[i]){ int sum = 0; for (int j = i;j <= n;j*=i) sum+=n/j; cnt[i]+=sum*delta; } } } int main(){ scanf("%d",&n); int tot = 0; for (int i = 1;i <= n;i++){ scanf("%d",&d[i]); if
(d[i]==0 && n!=1) return puts("0"),0; d[i]--; tot+=d[i]; } if (tot!=n-2) return puts("0"),0; for (int i = 2;i <= n;i++) if (ok(i)) is[i] = true; go(n-2,1); for (int i = 1;i <= n;i++) go(d[i],-1); long long temp = 1; for (int i = 1;i <= n;i++) for (int j = 1;j <= cnt[i];j++) temp = temp*i; printf("%lld\n",temp); return 0; }

【BZOJ 1211】 [HNOI2004]樹的計數