zoukankan      html  css  js  c++  java
  • 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);
    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
    " , ret);
    81         }
    82     }
    83     return 0;
    84 }

     

  • 相关阅读:
    Apache 虚拟主机 VirtualHost 配置
    EAX、ECX、EDX、EBX寄存器的作用
    Python中文文档 目录(转载)
    八度
    POJ 3268 Silver Cow Party (最短路)
    POJ 2253 Frogger (求每条路径中最大值的最小值,Dijkstra变形)
    2013金山西山居创意游戏程序挑战赛——复赛(1) HDU 4557 非诚勿扰 HDU 4558 剑侠情缘 HDU 4559 涂色游戏 HDU 4560 我是歌手
    HDU 4549 M斐波那契数列(矩阵快速幂+欧拉定理)
    UVA 11624 Fire! (简单图论基础)
    HDU 3534 Tree (树形DP)
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4537453.html
Copyright © 2011-2022 走看看