【樹】【數論】[BZOJ1005][HNOI2008]明明的煩惱
阿新 • • 發佈:2018-12-24
題目描述
自從明明學了樹的結構,就對奇怪的樹產生了興趣…… 給出標號為1到N的點,以及某些點最終的度數,允許在任意兩點間連線,可產生多少棵度數滿足要求的樹?
樣例輸入
3
1
-1
-1
樣例輸出
2
題目解析
首先我們根據prufer數列可以知道任意一棵無根樹可以表示為任意一個長度為
關於prufer唯一性其實很好證明如果兩個prufer的數列是一樣的那麼意味著每一個節點的每一個兒子數量相同,並且出入度和位置相同,那難道不一樣麼。
程式碼
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 1000;
int answ[MAXN+10], prime[MAXN+10], t[MAXN*10+10], d[MAXN+10];
bool notprime[MAXN+10];
void GetPrime(int Max){
int tmp;
for(int i=2;i<=Max;i++){
if(!notprime[i])
prime[++prime[0 ]] = i;
for(int j=1;j<=prime[0]&&(tmp=prime[j]*i)<=Max;j++){
notprime[tmp] = true;
if(i%prime[j] == 0)
break;
}
}
}
void add(int u, int m){
for(int i=1;i<=prime[0]&&u>1;i++){
while(u%prime[i]==0){
u /= prime[i];
answ[i] += m;
}
}
}
int main(){
int n;
scanf("%d", &n);
int sum=0, cnt=0, flag = 0;
GetPrime(1000);
int t1;
for(int i=1;i<=n;i++){
scanf("%d", &t1);
d[i] = t1;
if(t1 == 0 || t1 >= n) flag = 1;
if(t1 == -1){
continue;
}else{
cnt++;
sum += (--t1);
for(int j=1;j<=t1;j++)
add(j, -1);
}
}
t1 = n-2;
for(int i=1;i<=t1;i++)
add(i, 1);
if(n == 1){
if(t1 == -1) printf("1\n");
else printf("0\n");
return 0;
}
if(n == 2){
if((d[1]==0||d[1]>1) || (d[2]==0||d[2]>1)) printf("0\n");
else printf("1\n");
return 0;
}
if(flag){
printf("0\n");
return 0;
}
t1 = n-2-sum;
for(int i=1;i<=t1;i++)
add(i, -1);
add(n-cnt, n-2-sum);
t[0] = t[1] = 1;
for(int i=1;i<=prime[0];i++){
while(answ[i]){
answ[i]--;
for(int j=1;j<=t[0];j++)
t[j] *= prime[i];
for(int j=1;j<t[0];j++){
t[j+1] += t[j] / 10;
t[j] %= 10;
}
while(t[t[0]] >= 10){
t[t[0]+1] = t[t[0]]/10;
t[t[0]] %= 10;
t[0]++;
}
}
}
for(int i=t[0];i;i--)
printf("%d", t[i]);
printf("\n");
return 0;
}