COJ 1208 矩阵快速幂DP

  题目大意:

f(i) 是一个斐波那契数列 , 求sum(f(i)^k)的总和

由于n极大,所以考虑矩阵快速幂加速

我们要求解最后的sum[n]

首先我们需要思考

sum[n] = sum[n-1] + f(i+1)^k

那么很显然sum[n-1]是矩阵中的一个元素块

那么f(i+1)^k怎么利用f(i) , f(i-1)来求

f(i+1)^k = (f(i) + f(i-1)) ^ k

假如k = 1 , 可以看出f(i+1) = f(i-1) + f(i) (1,1)

      k = 2 , 可以看出f(i+1)^2 = f(i-1)^2 + 2*f(i-1)*f(i) + f(i)^2 (1 , 2 , 1)

后面只列出前面的因子 k=3          1 , 3 , 3 , 1

          k =4          1, 4 ,6,4,1

        很容易看出后一行的数是由前一行的数当前列和前一列的相加

那么这里要放入矩阵中思考的就是 f(i-1)^k , f(i-1)^(k-1)*f(i) ...... f(i)^k , sum[i] 这样 k+2 个元素

那么做矩阵快速幂就是利用f(i-1)^k , f(i-1)^(k-1)*f(i) ...... f(i)^k , sum[i]  乘以某一个矩阵得到

f(i)^k , f(i)^(k-1)*f(i+1) ...... f(i+1)^k , sum[i+1]

自己一个个递推就会渐渐利用上述的关系轻松得到这个矩阵

 

 1 #include <cstdio>

 2 #include <cstring>

 3 

 4 using namespace std;

 5 #define N 100

 6 #define ll long long

 7 const int MOD = 1000000007;

 8 int n , k , l;

 9 int num[N];

10 

11 struct Matrix{

12     int a[N][N];

13     Matrix operator*(const Matrix &m) const{

14         Matrix ans ;

15         for(int i=0 ; i<l ; i++){

16             for(int j=0 ; j<l ; j++){

17                 ans.a[i][j] = 0;

18                 for(int k=0 ; k<l ; k++){

19                     ans.a[i][j] += ((ll)a[i][k] * m.a[k][j])%MOD;

20                     ans.a[i][j] %= MOD;

21                 }

22             }

23         }

24         return ans;

25     }

26 }st;

27 

28 Matrix q_pow(Matrix b , int t)

29 {

30     Matrix ans;

31     memset(ans.a , 0 , sizeof(ans));

32     for(int i=0 ; i<l ; i++) ans.a[i][i] = 1;

33     while(t)

34     {

35         if(t&1) ans = ans*b;

36         b = b*b;

37         t>>=1;

38     }

39     return ans;

40 }

41 

42 void build_matrix()

43 {

44     memset(st.a , 0 , sizeof(st.a));

45     st.a[l-2][0] = 1;

46     for(int i=1 ; i<l-1 ; i++){

47         for(int j=l-2 , t=0 ; t<=i ; t++,j--){

48             st.a[j][i] = st.a[j][i-1]+st.a[j+1][i-1];

49         }

50     }

51     for(int i=0 ; i<l-1 ; i++)

52         st.a[i][l-1] = st.a[i][l-2];

53     st.a[l-1][l-1] = 1;

54 }

55 

56 int main()

57 {

58     #ifndef ONLINE_JUDGE

59         freopen("a.in" , "r" , stdin);

60     #endif // ONLINE_JUDGE

61     int T;

62     scanf("%d" , &T);

63     while(T--)

64     {

65         scanf("%d%d" , &n , &k);

66         l = k+2;

67         build_matrix();

68         for(int i=0 ; i<l-1 ; i++){

69             num[i] = 1;

70         }

71         num[l-1] = 2;

72         if(n<=2) printf("%d\n" , n);

73         else{

74             Matrix ans = q_pow(st , n-2);

75             int ret = 0;

76             for(int i=0 ; i<l ; i++){

77                 ret += num[i]*ans.a[i][l-1]%MOD;

78                 ret %= MOD;

79             }

80             printf("%d\n" , ret);

81         }

82     }

83     return 0;

84 }

 

 

 

你可能感兴趣的:(dp)