• HDU 2604 矩阵快速幂


    题目大意

    给定长度为l的只有f,m两种字母 的序列,问不出现fff,fmf的序列个数有多少个

    每次的下一个状态都与前一次状态的后两个字母有关

    比如我令mm : 0 , mf : 1 , fm : 2 , ff : 3;

    那么dp[i][j] 表示长度为i的序列最后由j状态结尾的总个数,当然 j 要大于2

    dp[i][0] = dp[i-1][0] + dp[i-1][2]

    dp[i][1] = dp[i-1][0]

    dp[i][2] = dp[i-1][1] + dp[i-1][3]

    dp[i][3] = dp[i-1][1]

    根据这个递推关系,我们就能很容易地用动态规划解这道题目,然后就发现超时了 。。。

    换个角度把dp值当作矩阵看 (dp[i][0] ,  dp[i][1] , dp[i][2] , dp[i][3]) = {{1 , 1 , 0 , 0} , {0 , 0 , 1, 1} , {1 , 0 , 0 ,0} , {0 , 0 ,1 , 0}} *(dp[i-1][0] ,  dp[i-1][1] , dp[i-1][2] , dp[i-1][3]) 

    然后连续乘法上进行优化

    while(n){

      if(n & 1) ~

      ~

      n>>=1

    }

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 using namespace std;
     5 int l , M;
     6 
     7 struct Matrix{
     8     int m[4][4];
     9     Matrix operator*(const Matrix &p)const {
    10         Matrix tmp;
    11         for(int i = 0 ; i < 4 ; i++)
    12             for(int j = 0 ; j<4 ; j++){
    13                 tmp.m[i][j] = 0;
    14                 for(int k = 0 ; k<4 ; k++){
    15                     tmp.m[i][j] += m[i][k] * p.m[k][j];
    16                     tmp.m[i][j] %= M;
    17                 }
    18             }
    19         return tmp;
    20     }
    21     void show(){
    22         for(int i = 0 ; i<4 ; i++){
    23             for(int j = 0 ; j<4 ; j++){
    24                 printf("%d " , m[i][j]);
    25             }
    26             puts("");
    27         }
    28     }
    29 };
    30 
    31 Matrix pow(Matrix a , int n)
    32 {
    33     Matrix tmp;
    34     memset(tmp.m , 0 , sizeof(tmp.m));
    35     //建立一个单位矩阵
    36     for(int i = 0 ; i<4 ; i++)
    37             tmp.m[i][i] = 1;
    38 
    39     while(n){
    40         if(n & 1) tmp = tmp*a;
    41         a = a * a;
    42         n >>= 1;
    43     }
    44     return tmp;
    45 }
    46 
    47 int main()
    48 {
    49     while(~scanf("%d%d" , &l , &M)){
    50         if(l == 0) puts("0");
    51         else if(l == 1) printf("%d
    " , 2%M);
    52         else{
    53             Matrix a;
    54             a.m[0][0] = 1 , a.m[0][1] = 1 , a.m[0][2] = 0 , a.m[0][3] = 0;
    55             a.m[1][0] = 0 , a.m[1][1] = 0 , a.m[1][2] = 1 , a.m[1][3] = 1;
    56             a.m[2][0] = 1 , a.m[2][1] = 0 , a.m[2][2] = 0 , a.m[2][3] = 0;
    57             a.m[3][0] = 0 , a.m[3][1] = 0 , a.m[3][2] = 1 , a.m[3][3] = 0;
    58 
    59             Matrix t = pow(a , l-2);
    60 
    61             int ans = 0;
    62             int b[4] = {1 , 1 , 1 , 1};
    63             for(int i = 0 ; i<4 ; i++)
    64                 for(int j = 0 ; j<4 ; j++){
    65                     ans += b[j] * t.m[j][i];
    66                 }
    67             printf("%d
    " , ans % M);
    68         }
    69     }
    70     return 0;
    71 }
  • 相关阅读:
    java实现万年历
    java中关于Calendar
    java中各种类型的输入输出
    java(向上向下转型)
    MyEclipse还原默认窗口
    Hibernate映射问题之OneToOne【自己整理】
    Neither BindingResult nor plain target object for bean
    剑宗与气宗
    分治算法
    spring处理线程并发
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4187677.html
Copyright © 2020-2023  润新知