有了bzoj1430的经验解决这题就不是什么难事了
首先考虑度数确定的点,令tot=sigma(d[i]-1)
首先给这tot个数分配prufer编码的位置有C(tot,n-2)种方案
每个方案中是可以进行可重复排列的,对应tot!/[(d[1]-1)!*(d[2]-1)!*…*(d[k]-1)!] 这里都是已确定的度数的点
下面考虑无所谓的点,这些可以在prufer序列中随意分配
因此答案是m^(n-2-tot) (m表示未确定度数的点的个数)
根据乘法原理答案就是C(tot,n-2)*m^(n-2-tot)*tot!/[(d[1]-1)!*(d[2]-1)!*…*(d[k]-1)!]
=(n-2)!*m^(n-2-tot)/[(d[1]-1)!*(d[2]-1)!*…*(d[k]-1)!*(n-2-tot)!]
肯定要高精度,但是我们要尽量避免除法
考虑到这里计算出的方案一定是整数,于是我们可以先质因数分解,然后消去,这要就是单精度的高精度乘法了
1 var d:array[0..1010,0..1010] of longint; 2 a,p,c:array[0..1010] of longint; 3 ans:array[0..100010] of longint; 4 l,i,m,x,n,w,j,t:longint; 5 f:boolean; 6 7 procedure mul(x,y:longint); 8 var i,j,u,v:longint; 9 begin 10 for i:=1 to y do 11 begin 12 v:=0; 13 for j:=1 to l do 14 begin 15 u:=ans[j]*x+v; 16 v:=u div 10; 17 ans[j]:=u mod 10; 18 end; 19 while v>0 do 20 begin 21 inc(l); 22 ans[l]:=v mod 10; 23 v:=v div 10; 24 end; 25 end; 26 end; 27 28 begin 29 readln(n); 30 for i:=2 to n do 31 begin 32 f:=true; 33 for j:=2 to trunc(sqrt(i)) do 34 if i mod j=0 then 35 begin 36 f:=false; 37 break; 38 end; 39 if f then 40 begin 41 inc(t); 42 p[t]:=i; 43 end; 44 end; 45 for i:=1 to n do 46 begin 47 readln(a[i]); 48 if a[i]<>-1 then m:=m+a[i]-1 49 else inc(w); 50 end; 51 for i:=2 to n-2 do 52 begin 53 for j:=1 to t do 54 d[i,j]:=d[i-1,j]; 55 x:=i; 56 j:=1; 57 while x<>1 do //预处理阶乘的质因数分解 58 begin 59 while (x<>1) and (x mod p[j]=0) do 60 begin 61 x:=x div p[j]; 62 inc(d[i,j]); 63 end; 64 inc(j); 65 end; 66 end; 67 ans[1]:=1; 68 l:=1; 69 x:=w; 70 j:=1; 71 while x<>1 do //m^(n-2-tot)的质因数分解 72 begin 73 while (x<>1) and (x mod p[j]=0) do 74 begin 75 x:=x div p[j]; 76 c[j]:=c[j]+(n-2-m); 77 end; 78 inc(j); 79 end; 80 81 for i:=1 to t do 82 c[i]:=c[i]+d[n-2,i]-d[n-2-m,i]; 83 84 for i:=1 to n do 85 if a[i]<>-1 then 86 begin 87 for j:=1 to t do 88 c[j]:=c[j]-d[a[i]-1,j]; 89 end; 90 for i:=1 to t do 91 mul(p[i],c[i]); 92 for i:=l downto 1 do 93 write(ans[i]); 94 writeln; 95 end. 96 97