首页 > 代码库 > [BZOJ 1002](FJOI 2007) 轮状病毒

[BZOJ 1002](FJOI 2007) 轮状病毒

【题目描述】

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

【输入格式】

第一行有1个正整数n。

【输出格式】

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

【样例输入】

3

【样例输出】

16

【题目来源】

耒阳大世野(衡阳八中) OJ 1002

(福建省选赛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 }
高精度 + 递推

 

[BZOJ 1002](FJOI 2007) 轮状病毒