码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj1002 生成树计数 找规律

时间:2015-02-15 23:00:56      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:

 

这道题第一眼是生成树计数,n是100,是可以用O(n^3)的求基尔霍夫矩阵的n-1阶的子矩阵的行列式求解的,但是题目中并没有说取模之类的话,就不好办了。

用高精度?有分数出现。

用辗转相除的思想,让它不出现分数。但过程中会出现负数,高精度处理负数太麻烦。

用Python打表?好吧,Python还不熟,写不出来。。。。。

所以,如果这道题我考场上遇到,最多用double骗到n<=20的情况的部分分。

 

最终只能求助于题解了。。。

好像是通过观察行列式的特点,推导出关于答案f(n)的递推式(f(n)=3*f(n-1)-f(n-2)+2)

这道题就这样水过了,收获是:

  1、题目可能属于某一类问题,该类问题又有通法可解,但题目一般不能直接套用之,此时就只能观察题目较之一般问题的特殊之处,尝试利用它帮助解题。

  2、当1行不通时,可以先用暴力把规模较小的解跑出来,再看看可否推出规律。

 

回顾一下高精:

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #define M 10
 5 using namespace std;
 6 
 7 struct Num {
 8     int v[100], len;
 9     Num(){}
10     Num( int n ) {
11         memset( v, 0, sizeof(v) );
12         if( n==0 ) {
13             len = 1;
14             return;
15         }
16         len = 0;
17         while( n ) {
18             len++;
19             v[len] = n%M;
20             n /= M;
21         }
22     }
23     Num operator+( const Num &b ) const {
24         Num rt(0);
25         rt.len = max( len, b.len ) + 1;
26         for( int i=1; i<=rt.len; i++ ) {
27             rt.v[i] += v[i]+b.v[i];
28             rt.v[i+1] += rt.v[i]/M;
29             rt.v[i] %= M;
30         }
31         while( rt.len>1 && rt.v[rt.len]==0 ) rt.len--;
32         return rt;
33     }
34     Num operator-( const Num &b ) const {
35         Num rt(0);
36         rt.len = len;
37         for( int i=1; i<=rt.len; i++ ) {
38             rt.v[i] += v[i]-b.v[i];
39             if( rt.v[i]<0 ) {
40                 rt.v[i]+=M;
41                 rt.v[i+1]--;
42             }
43         }
44         while( rt.len>1 && rt.v[rt.len]==0 ) rt.len--;
45         return rt;
46     }
47     int count_bit( int b ) const {
48         int rt = 0;
49         while( b ) {
50             rt++;
51             b/=M;
52         }
53         return rt;
54     }
55     Num operator*( int b ) const {
56         Num rt(0);
57         rt.len = len+count_bit(b)+1;    //    b==3
58         for( int i=1; i<=rt.len; i++ ) {
59             rt.v[i] += v[i]*b;
60             rt.v[i+1] += rt.v[i]/M;
61             rt.v[i] %= M;
62         }
63         while( rt.len>1 && rt.v[rt.len]==0 ) rt.len--;
64         return rt;
65     }
66     void print() {
67         for( int i=len; i>=1; i-- )
68             printf( "%d", v[i] );
69         printf( "\n" );
70     }
71 };
72 
73 int n;
74 Num dp[110];
75 
76 int main() {
77     scanf( "%d", &n );
78     dp[1] = Num(1);
79     dp[2] = Num(5);
80     for( int i=3; i<=n; i++ )
81         dp[i] = dp[i-1]*3 +Num(2) - dp[i-2];
82     dp[n].print();
83 }
View Code

 

bzoj1002 生成树计数 找规律

标签:

原文地址:http://www.cnblogs.com/idy002/p/4293556.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!