P2144 [FJOI2007]輪狀病毒
阿新 • • 發佈:2018-03-10
orz 神奇 OS view event alt math AI pic
輸出樣例#1: 復制
P2144 [FJOI2007]輪狀病毒
題目描述
輪狀病毒有很多變種。許多輪狀病毒都是由一個輪狀基產生。一個n輪狀基由圓環上n個不同的基原子和圓心的一個核原子構成。2個原子之間的邊表示這2個原子之間的信息通道,如圖1。
n輪狀病毒的產生規律是在n輪狀基中刪除若幹邊,使各原子之間有唯一一條信息通道。例如,共有16個不同的3輪狀病毒,入圖2所示。
給定n(N<=100),編程計算有多少個不同的n輪狀病毒。
輸入輸出格式
輸入格式:
第一行有1個正整數n。
輸出格式:
將編程計算出的不同的n輪狀病毒數輸出
輸入輸出樣例
輸入樣例#1: 復制3
16
分析
首先想到的是生成樹計數,數據範圍也剛剛好,然後不過QAQ。
在網上看到大神一個神奇的式子:F(n)為n輪狀病毒的個數,F(n) = 3F(n - 1) - F(n - 2) + 2
也可以搜索,打表,找規律。。。orz
不過需要高精度。。於是找到了一個Python代碼。
code
python
1 n=int(raw_input()) 2 f=[0]*105 3 f[1]=1 4 for i in range(2,101): 5 f[i]=3*f[i-1]-f[i-2]+2 6 printView Code(f[n])
40分Matrix-tree定理求生成樹計數。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 6 using namespace std; 7 const double eps = 1e-12; 8 double c[110][110],ans; 9 int n; 10 11 void build() { 12 int M = n+1View Code; 13 for (int i=1; i<n; ++i) c[i][i+1] = c[i+1][i] = -1; 14 c[n][1] = c[1][n] = -1; 15 for (int i=1; i<=n; ++i) { 16 c[i][i] = 3; 17 c[i][M] = c[M][i] = -1; 18 } 19 c[M][M] = n; 20 } 21 void Gauss() { 22 for (int k=1; k<=n; ++k) { 23 int r = k; 24 for (int i=k+1; i<=n; ++i) 25 if (fabs(c[i][k]) > fabs(c[r][k])) r = i; 26 if (r != k) for (int j=1; j<=n; ++j) swap(c[r][j],c[k][j]); 27 for (int i=k+1; i<=n; ++i) 28 if (fabs(c[i][k]) > eps) { 29 double t = c[i][k] / c[k][k]; 30 for (int j=k; j<=n; ++j) c[i][j] -= t*c[k][j]; 31 } 32 } 33 ans = 1.0; 34 for (int i=1; i<=n; ++i) ans *= c[i][i]; 35 ans = ans<0?-ans:ans; 36 } 37 int main() { 38 scanf("%d",&n); 39 build(); 40 Gauss(); 41 printf("%.0lf\n",ans+eps); 42 return 0; 43 }
P2144 [FJOI2007]輪狀病毒