[BZOJ1002](FJOI 2007) 轮状病毒
【题目描述】
给定n(N<=100),编程计算有多少个不同的n轮状病毒。
【输入格式】
第一行有1个正整数n。
【输出格式】
将编程计算出的不同的n轮状病毒数输出
【样例输入】
3
【样例输出】
16
【题目来源】
(福建省选赛2007)
【分析】
从“各原子有唯一的信息通道”不难看出,每种轮状病毒对应着轮状基的一棵生成树。一般图的生成树计数可以用Matrix-Tree 定理求解,但这里的图比较特殊,用Matrix-Tree未免有些小题大做, 我们可以用组合递推的方法求解。
先设$f(n)$为n轮状基上删去一条弧得到的“缺口轮”上的生成树个数,再设$S(n) = \sum \limits_{i = 1}^n {f(i)}$. 于是就有:
$$\begin{array}{F} f(0) = f(1) = 1\\ f(n) = 2f(n-1) + \sum_{i=0}^{n-2} f(i) = f(n-1) + S(n-1) + 1 \end{array}$$
$$ans(n) = f(n) + 2\sum_{i = 1}^{n-1}f(i) = S(n) + S(n-1)$$
(这个公式我推了一上午我会说?)
考虑到n最大为100,答案会超过long long的范围,这里的状态值应用高精度类存储。
1 /**************************************************************
2 Problem: 1002
3 User: 935671154
4 Language: C++
5 Result: Accepted
6 Time:44 ms
7 Memory:2068 kb
8 ****************************************************************/
9
10 //Author : Asm.Def
11 #include <iostream>
12 #include <cctype>
13 #include <cstdio>
14 #include <vector>
15 #include <algorithm>
16 #include <cmath>
17 #include <queue>
18 using namespace std;
19 inline void getd(int &x){
20 char c = getchar();
21 bool minus = 0;
22 while(!isdigit(c) && c != '-')c = getchar();
23 if(c == '-')minus = 1, c = getchar();
24 x = c - '0';
25 while(isdigit(c = getchar()))x = x * 10 + c - '0';
26 if(minus)x = -x;
27 }
28 /*======================================================*/
29 const int maxn = 102;
30
31 struct BigN{
32 #define base 10000
33 #define maxl 1000
34 int A[maxl], len;
35 BigN(){len = 1, A[0] = 0;}
36 BigN &operator = (const BigN &x){
37 len = 0;
38 while(len < x.len){A[len] = x.A[len]; ++len;}
39 return *this;
40 }
41 BigN &operator = (int k){len = 1;A[0] = k; return *this;}
42 BigN &operator += (const BigN &x){
43 int i, mor = 0;
44 for(i = 0;i < x.len || mor;++i){
45 if(i < len)mor += A[i];
46 if(i < x.len)mor += x.A[i];
47 A[i] = mor % base;
48 mor /= base;
49 }
50 if(i > len)len = i;
51 return *this;
52 }
53 }f[maxn], S[maxn];
54
55 inline void work(int k){
56 int i;
57 if(!k){printf("0\n");return;}
58 f[0] = 1, f[1] = 1, S[1] = 1;
59 if(k == 1){printf("1\n");return;}
60 for(i = 2;i <= k;++i){
61 f[i] = 1; f[i] += f[i-1]; f[i] += S[i-1];
62 S[i] = S[i-1]; S[i] += f[i];
63 }
64 S[k] += S[k-1];
65 i = S[k].len - 1;
66 printf("%d", S[k].A[i]);
67 while(i)
68 printf("%04d", S[k].A[--i]);
69 putchar('\n');
70 }
71
72 int main(){
73 #if defined DEBUG
74 freopen("test", "r", stdin);
75 #endif
76 int k;
77 getd(k);
78
79 work(k);
80
81 #if defined DEBUG
82 cout << endl << (double)clock()/CLOCKS_PER_SEC << endl;
83 #endif
84 return 0;
85 }
2 Problem: 1002
3 User: 935671154
4 Language: C++
5 Result: Accepted
6 Time:44 ms
7 Memory:2068 kb
8 ****************************************************************/
9
10 //Author : Asm.Def
11 #include <iostream>
12 #include <cctype>
13 #include <cstdio>
14 #include <vector>
15 #include <algorithm>
16 #include <cmath>
17 #include <queue>
18 using namespace std;
19 inline void getd(int &x){
20 char c = getchar();
21 bool minus = 0;
22 while(!isdigit(c) && c != '-')c = getchar();
23 if(c == '-')minus = 1, c = getchar();
24 x = c - '0';
25 while(isdigit(c = getchar()))x = x * 10 + c - '0';
26 if(minus)x = -x;
27 }
28 /*======================================================*/
29 const int maxn = 102;
30
31 struct BigN{
32 #define base 10000
33 #define maxl 1000
34 int A[maxl], len;
35 BigN(){len = 1, A[0] = 0;}
36 BigN &operator = (const BigN &x){
37 len = 0;
38 while(len < x.len){A[len] = x.A[len]; ++len;}
39 return *this;
40 }
41 BigN &operator = (int k){len = 1;A[0] = k; return *this;}
42 BigN &operator += (const BigN &x){
43 int i, mor = 0;
44 for(i = 0;i < x.len || mor;++i){
45 if(i < len)mor += A[i];
46 if(i < x.len)mor += x.A[i];
47 A[i] = mor % base;
48 mor /= base;
49 }
50 if(i > len)len = i;
51 return *this;
52 }
53 }f[maxn], S[maxn];
54
55 inline void work(int k){
56 int i;
57 if(!k){printf("0\n");return;}
58 f[0] = 1, f[1] = 1, S[1] = 1;
59 if(k == 1){printf("1\n");return;}
60 for(i = 2;i <= k;++i){
61 f[i] = 1; f[i] += f[i-1]; f[i] += S[i-1];
62 S[i] = S[i-1]; S[i] += f[i];
63 }
64 S[k] += S[k-1];
65 i = S[k].len - 1;
66 printf("%d", S[k].A[i]);
67 while(i)
68 printf("%04d", S[k].A[--i]);
69 putchar('\n');
70 }
71
72 int main(){
73 #if defined DEBUG
74 freopen("test", "r", stdin);
75 #endif
76 int k;
77 getd(k);
78
79 work(k);
80
81 #if defined DEBUG
82 cout << endl << (double)clock()/CLOCKS_PER_SEC << endl;
83 #endif
84 return 0;
85 }