随笔- 3  文章- 0  评论- 0 

这里是题目地址

题目意思很简单,就是已知n,k计算:

其中是斐波那契数列第n-1项。n的范围是[1,1e17] ,k的范围是[1,40]

看了一下觉得是快速幂,不过计算能力蒟蒻,纸上划了一天才得到结果 _(:з」∠)_

定义:

算一下:

这样就有了线性迭代式,然后可以构造矩阵出来:

然后用矩阵快速幂就可以搞定了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #define ll long long 
 5 using namespace std ;
 6 int n ,c[50][50] ={1} ;
 7 const int mod = 1e9+7 ;
 8 struct MAT{
 9     ll a[90][90] ;
10     MAT(){ memset( this ,0 ,sizeof(MAT) ) ; }
11 };
12 MAT multi( MAT a ,MAT b ){
13     MAT ret;
14     for( int i = 0 ;i < n ;i ++ )
15         for( int j = 0 ;j < n ;j ++ ){
16             for( int k = 0 ;k < n ;k ++ ){
17                 ret.a[i][j] += a.a[i][k] * b.a[k][j];
18                 ret.a[i][j] %= mod;
19             }
20         }
21     return ret;
22 }
23 MAT Qpow( MAT a ,ll b ){
24     MAT ret;
25     for( int i = 0 ;i < n ;i ++ ) 
26         ret.a[i][i]=1;
27     while( b ){
28         if( b & 1 )
29             ret = multi( ret ,a );
30         b /= 2;
31         a = multi( a ,a );
32     }
33     return ret;
34 }
35 int main(){
36     ll t ,k ;
37     cin >> t >> k ;
38     n = 2 * k + 3 ;
39     MAT base ;
40     for( int i = 0 ;i <= k ;i ++ ){
41         c[i][0] = 1 ;
42         for( int j = 1 ;j <= i ;j ++ ){
43             c[i][j] = ( c[i-1][j-1] + c[i-1][j] ) % mod ;
44         }
45     }
46     for( int i = 0 ;i <= k ;i ++ ){
47         for( int j = 0 ;j <= i ;j ++ ){
48             base.a[i+k+1][j] = base.a[i][j] = base.a[i][j+k+1] = c[i][j] ;
49         }
50     }
51     base.a[k+k+2][k] = base.a[k+k+2][k+k+2] = 1 ;
52 
53     MAT ans = Qpow( base ,t ) ;
54     ll a = 0 ;
55     for( int i = 0 ;i < 2*k+2 ;i ++ ) 
56         a = ( a + ans.a[k+k+2][i] ) % mod  ;
57     cout << a << endl ;
58 }
CODE

 

 posted on 2014-02-19 19:58 MyWither 阅读(...) 评论(...) 编辑 收藏