【BZOJ1211】树的计数(Prufer编码)

题意:一个有n个结点的树,设它的结点分别为v1, v2, …, vn,

已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵。

其中1<=n<=150,输入数据保证满足条件的树不超过10^17个。

思路:

Martix67:

一个有趣的推广是,n个节点的度依次为D1, D2, …, Dn的无根树共有(n-2)! / [ (D1-1)!(D2-1)!..(Dn-1)! ]个,因为此时Prüfer编码中的数字i恰好出现Di-1次。

POPOQQQ:

注意此题无解需要输出0

当n!=1&&d[i]==0时 输出0

当Σ(d[i]-1)!=n-2时输出0

 1 var a,b,prime,cnt:array[0..1000]of longint;
 2     n,m,s,i:longint;
 3     ans:int64;
 4     flag:boolean;
 5 
 6 function mult(x,y:longint):int64;
 7 var tmp:int64;
 8 begin
 9  mult:=1; tmp:=x;
10  while y>0 do
11  begin
12   if y and 1=1 then mult:=mult*tmp;
13   tmp:=tmp*tmp;
14   y:=y>>1;
15  end;
16 end;
17 
18 function ins(x,y:longint):longint;
19 var i,k:longint;
20 begin
21  for i:=1 to m do
22  begin
23   k:=x;
24   while k>0 do
25   begin
26    cnt[i]:=cnt[i]+k div prime[i]*y;
27    k:=k div prime[i];
28   end;
29  end;
30 end;
31 
32 function su(x:longint):boolean;
33 var i:longint;
34 begin
35  if x=2 then exit(true);
36  for i:=2 to trunc(sqrt(x)) do
37   if x mod i=0 then exit(false);
38  exit(true);
39 end;
40 
41 begin
42  assign(input,'bzoj1211.in'); reset(input);
43 // assign(output,'bzoj1211.out'); rewrite(output);
44  readln(n);
45  for i:=2 to 150 do
46   if su(i) then begin inc(m); prime[m]:=i; end;
47  for i:=1 to n do
48  begin
49   read(a[i]);
50   inc(b[a[i]]);
51   s:=s+a[i]-1;
52  end;
53  if n-2<>s then
54  begin
55   writeln(0);
56   exit;
57  end;
58  flag:=true;
59  for i:=1 to n do
60   if a[i]=0 then begin flag:=false; break; end;
61  if (n>1)and( not flag) then
62  begin
63   writeln(0);
64   exit;
65  end;
66 
67  ins(n-2,1);
68  for i:=1 to n do
69   if b[i]-1>0 then ins(b[i]-1,-1);
70  ans:=1;
71  for i:=1 to m do ans:=ans*mult(prime[i],cnt[i]);
72  writeln(ans);
73 
74  close(input);
75  //close(output);
76 end.
原文地址:https://www.cnblogs.com/myx12345/p/6490745.html