HLG 1375 The Active Leyni

来源:互联网 发布:win7远程桌面端口号 编辑:程序博客网 时间:2024/06/13 08:36

递推公式+矩阵乘方

转:(有个写的特别好,我就直接引用下了偷笑


定义f[i][0]为走了i步恰好达到S的不同走法

定义f[i][1]为走了i步恰好达到A的不同走法

定义f[i][2]为走了i步恰好达到B的不同走法

定义f[i][3]为走了i步恰好达到C的不同走法

状态转义方程为:

f[i][0] = f[i – 1][1] + f[i – 1][2] + f[i – 1][3];

f[i][1] = f[i – 1][0] + f[i – 1][2] + f[i – 1][3];

f[i][2] = f[i – 1][0] + f[i – 1][1] + f[i – 1][3];

f[i][3] = f[i – 1][0] + f[i – 1][1] + f[i – 1][2];

由于n的规模达到109,所以我们可以令

矩阵A = [1 0 0 0]表示走了0步时恰好到达S, A, B, C的不同走法,

那么每次状态转义相当于乘以矩阵B,其中:

B = [0 1 1 1

       1 0 1 1

       1 1 0 1

       1 1 1 0]

可知,求走n步恰好到达S点的不同走法即是求A * Bn,使用矩阵快速幂乘法即可。

快速幂:http://blog.csdn.net/masked__dance/article/details/40264411

矩阵乘方,优化递推公式:http://blog.csdn.net/masked__dance/article/details/40351293

#include <iostream>#include <stdio.h>#include <string.h>using namespace std;#define mod 1000000007void mul(long long a[][4],long long b[][4]){    long long c[4][4];    for(int i=0;i<4;i++)    for(int j=0;j<4;j++){        c[i][j]=0;        for(int k=0;k<4;k++)            c[i][j]+=((a[i][k]%mod)*(b[k][j]%mod))%mod;    }    for(int i=0;i<4;i++)        for(int j=0;j<4;j++)        b[i][j]=c[i][j]%mod;}long long quickPow(long long m,long long co[][4],long long a[][4]){    while(m){        if(m&1)            mul(co,a);        mul(co,co);        m>>=1;    }    return a[0][0];}int main(){    long long T,m;    scanf("%lld",&T);    while(T--)    {        scanf("%lld",&m);        long long        A[4][4]={1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};        long long co[4][4]={0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0};        cout<<quickPow(m,co,A)<<endl;    }    return 0;}


0 0