[矩阵快速幂] fzu 2117 特殊的数

来源:互联网 发布:花衣吹笛手 知乎 编辑:程序博客网 时间:2024/06/03 18:48

题意:

中文题不解释

注意是n位数!

思路:

中文在群里问了大神们,终于领悟到这种递推的精华

对于给定的n都会包含有四种状态

0、7和9的个数都是奇数

1、7是奇数,9是偶数

2、7是偶数,9是奇数

3、7是偶数,9是偶数

显然状态3是我们要状态,但是他们之间是可以互相转移的

所以对于每次添加一个空位放数字,建立转移矩阵

| 3 1 1 0 |

| 1 3 0 1 |

| 1 0 3 1 |

| 0 1 1 3 |

初始状态为 (0,0,0,1)

然后就是n次方了~利用矩阵快速幂

最后ans.mat[0][3]就是答案了

代码:

#include"cstdlib"#include"cstdio"#include"cstring"#include"cmath"#include"queue"#include"algorithm"#include"iostream"using namespace std;__int64 mod=1000000007;struct matrix{    __int64 mat[5][5];};matrix matmul(matrix a,matrix b,int n,int m){    int i,j,k;    matrix c;    memset(c.mat,0,sizeof(c.mat));    for(i=0;i<n;i++)    {        for(j=0;j<n;j++)        {            for(k=0;k<n;k++)            {                c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];                c.mat[i][j]%=m;            }        }    }    return c;}matrix matpow(matrix a,__int64 k,int n,int m){    matrix b;    int i;    memset(b.mat,0,sizeof(b.mat));    for(i=0;i<n;i++) b.mat[i][i]=1;    while(k)    {        if(k&1) b=matmul(a,b,n,m);        a=matmul(a,a,n,m);        k>>=1;    }    return b;}int main(){    int t;    cin>>t;    while(t--)    {        matrix a,b,ans;        memset(a.mat,0,sizeof(a.mat));        memset(b.mat,0,sizeof(b.mat));        a.mat[0][3]=1;        for(int i=0;i<4;i++)        {            for(int j=0;j<4;j++)            {                if(i==j) b.mat[i][j]=3;                else if(i+j==3) b.mat[i][j]=0;                else b.mat[i][j]=1;            }        }        __int64 k;        scanf("%I64d",&k);        ans=matmul(a,matpow(b,k,4,mod),4,mod);        __int64 sum=0;        printf("%I64d\n",ans.mat[0][3]);    }    return 0;}



0 0
原创粉丝点击