gggyt  
没谁离不开谁

 

  矩阵快速幂可以想象为线性代数的矩阵相乘,主要是运用于高效的计算矩阵高次方。

  将矩阵两两分组,若要求a^n,即知道a^(n/2)次方即可,矩阵快速幂便是运用的这个思路。

  比方想求(A)^7那么(A)^6=(A*A)*(A*A)*(A*A),我们知道A*A此时再算三次便可得到答案,比起原先的计算已经简便了很多。

  矩阵快速幂的主要思路是找到关键的那个矩阵,并把它构建出来,此时思路就基本差不多了。

  举例:Hdu2604

    题意:f和m两种字母组成字符串,fmf 和 fff 这种为不安全的字符串,现在有2*L个字母,问你有多少安全的字符串。答案mod M。

    我们将0, 1, 2, 3, 4, 5的答案算出来我们便可以得到一个公式f(n)=f(n-1)+f(n-3)+f(n-4),此时我们要做的便是构建那个矩阵,如何构建呢。

我们可以得到这样的一个矩阵。

 

int n, modd;
int a[4], f[4];

struct Matrix{
    ll mat[4][4];
    Matrix operator*(const Matrix& m)const{
        Matrix tmp;
        for (int i=0; i <4; i++) {
            for (int j=0; j<4; j++) {
                tmp.mat[i][j]=0;
                for (int k=0; k<4; k++) {
                    tmp.mat[i][j] += mat[i][k]*m.mat[k][j]%modd;
                    tmp.mat[i][j]%=modd;
                }
            }
        }
        return tmp;
    }
};
ll Pow(Matrix &m, int k) {
    Matrix ans;
    memset(ans.mat, 0, sizeof(ans.mat));
    for (int i = 0; i < 4; i++)  ans.mat[i][i]=1;
    while(k) {
        if (k&1)  ans=ans*m;
        k>>=1;
        m=m*m;
    }
    ll sum=0;
    for (int i = 0; i < 4; i++)  {
        sum += ans.mat[0][i]*f[3-i]%modd;
        sum%=modd;
    }
    return sum%modd;
}
void solve() {
    Matrix m;
    f[0]=1, f[1]=2, f[2]=4, f[3]=6;
    while(scanf("%d%d", &n, &modd)!=EOF) {
        if (n<4)  printf("%d\n", f[n]%modd);
        else {
            memset(m.mat, 0, sizeof(m.mat));
            m.mat[0][0]=m.mat[0][2]=m.mat[0][3]=1;
            m.mat[1][0]=m.mat[2][1]=m.mat[3][2]=1;
            printf("%d\n", Pow(m, n-3)%modd);
        }
    }
}

  

 

posted on 2017-03-27 21:23  gggyt  阅读(168)  评论(0编辑  收藏  举报