洛谷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 }
于是乎就乱推公式,得到
轮状病毒的方案数满足递推式F(n) = 3 * F(n - 1) - F(n - 2) + 2,其中F(1) = 1, F(2) = 5
加上高精度即可