[Bzoj]1002: [FJOI2007]轮状病毒

Description

  轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的。一个N轮状基由圆环上N个不同的基原子
和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道。如下图所示

  N轮状病毒的产生规律是在一个N轮状基中删去若干条边,使得各原子之间有唯一的信息通道,例如共有16个不
同的3轮状病毒,如下图所示

  现给定n(N<=100),编程计算有多少个不同的n轮状病毒

 

Input

  第一行有1个正整数n

Output

  计算出的不同的n轮状病毒数输出

Sample Input

3

Sample Output

16
 
基尔霍夫矩阵:F[i]=(F[i-1]*3-F[i-2]+2)
高精度是必须的
 1 #include<iostream>
 2 #include<cstring>
 3 #include<iomanip>
 4 using namespace std;
 5 
 6 const int MAXN=100000;
 7 const int WIDE=10000;
 8 
 9 int n;
10 int F[101][MAXN]={0},L[101];
11 
12 void Mult(int *A,int *B,int &LA,int &LB,int n)
13 {
14     memset(B,0,sizeof(int)*MAXN);LB=LA+1;
15     for(int i=0;i<LA;i++)
16     {
17         B[i]+=A[i]*n;
18         if(B[i]>=WIDE)
19         {
20             B[i+1]+=B[i]/WIDE;
21             B[i]%=WIDE;
22         }
23     }
24     if(B[LB]>0) LB++;
25 }
26 
27 void Dec(int *A,int *B,int &LA,int &LB)
28 {
29     int T[MAXN];
30     int L=max(LA,LB);
31     memset(T,0,sizeof(T));
32     for(int i=0;i<L;i++)
33     {
34         T[i]+=A[i]-B[i];
35         if(T[i]<0)
36             T[i]+=WIDE,T[i+1]--;
37     }
38     while(T[L-1]==0) L--;
39     for(int i=0;i<L;i++)
40         A[i]=T[i];
41     LA=L;
42 }
43 
44 void Add(int *A,int &L,int n)
45 {
46     A[0]+=n;
47     A[L]=0;//不知道为什么A[L]会等于1,害我调试好久
48     for(int i=0;i<L;i++)
49     {
50         if(A[i]>=WIDE)
51             A[i]-=WIDE,A[i+1]++;
52     }
53     if(A[L]>0) L++;
54 }
55 
56 int main()
57 {
58     cin>>n;
59     F[1][0]=1;F[2][0]=5;
60     for(int i=1;i<=n;i++) L[i]=1;
61     for(int i=3;i<=n;i++)
62     {
63         Mult(F[i-1],F[i],L[i-1],L[i],3);
64         Dec(F[i],F[i-2],L[i],L[i-2]);
65         Add(F[i],L[i],2);
66     }
67     cout<<F[n][L[n]-1];
68     for(int i=L[n]-2;i>=0;i--)
69     {
70         cout.width(4);
71         cout.fill('0');
72         cout<<F[n][i];
73     }
74     return 0;
75 }

 

posted @ 2016-10-14 17:43  InWILL  阅读(283)  评论(0编辑  收藏  举报