洛谷P2144 [FJOI2007]轮状病毒

可以用Matrix-Tree定理,然而被卡精度

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<iostream>
 6 #define MAXN 100+10
 7 #define EPS 0.00000001
 8 using namespace std;
 9 bool zero(double x){
10     return (-EPS<x&&x<EPS);
11 }
12 double det(double a[MAXN][MAXN],int n){
13     double b[MAXN][MAXN],ret=1;
14     int sign=0;
15     memcpy(b,a,sizeof(b));
16     for(int i=1;i<=n;i++){
17         if(zero(b[i][i])){
18             int k=i;
19             while(zero(b[k][i]))k++;
20             if(k>n){
21                 return 0;
22             }
23             for(int j=i;j<=n;j++){
24                 swap(b[k][j],b[i][j]);
25             }    
26             sign++;
27         }    
28         ret*=b[i][i];
29         for(int j=i+1;j<=n;j++){
30             b[i][j]/=b[i][i];
31         }
32         for(int k=i+1;k<=n;k++){
33             for(int j=i+1;j<=n;j++){
34                 b[k][j]-=b[k][i]*b[i][j];
35             }    
36         }
37     }
38     if(sign&1){
39         ret=-ret;
40     }
41     return ret;
42 }
43 double A[MAXN][MAXN];
44 int v[MAXN];
45 int n;
46 void init(){
47     v[1]=n;
48     n++;
49     for(int i=2;i<=n;i++){
50         v[i]=3;
51     }
52     for(int i=1;i<=n;i++){
53         for(int j=1;j<=n;j++){
54             if(i==j){
55                 A[i][j]=v[i];
56             }    
57             else{
58                 if(i==1||j==1||i==n&&j==2||i==2&&j==n){
59                     A[i][j]=-1;
60                 }
61                 else if(i-j==1||j-i==1){
62                     A[i][j]=-1;
63                 }
64                 else{
65                     A[i][j]=0;
66                 }
67             }
68         }
69     }
70 }
71 void solve(){
72     printf("%.0f\n",det(A,n-1));
73 }
74 int main()
75 {
76     scanf("%d",&n);
77     if(n==1){
78         printf("1\n");
79         return 0;    
80     }
81     if(n==2){
82         printf("5\n");    
83         return 0;
84     }
85     init();
86     solve();
87     return 0;
88 }
View Code

于是乎就乱推公式,得到

轮状病毒的方案数满足递推式F(n) = 3 * F(n - 1) - F(n - 2) + 2,其中F(1) = 1, F(2) = 5

加上高精度即可

posted @ 2017-12-18 00:22  white_hat_hacker  阅读(156)  评论(0编辑  收藏  举报