poj3420

来源:互联网 发布:mac pro 2016屏幕涂层 编辑:程序博客网 时间:2024/05/11 22:12
#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>using namespace std;typedef vector<int> vec;typedef vector<vec> mat;int n,m;mat mul(mat &a,mat &b){    mat c(a.size(),vec(b[0].size()));    for(int i=0;i<a.size();i++)\    {        for(int k=0;k<b.size();k++)        {            for(int j=0;j<b[0].size();j++)            {                c[i][j]=(c[i][j]+a[i][k]*b[k][j])%m;            }        }    }    return c;}mat pow(mat a,int n){    mat b(a.size(),vec(a.size()));    for(int i=0;i<a.size();i++)        b[i][i]=1;    while(n>0)    {        if(n&1)            b=mul(b,a);        a=mul(a,a);        n>>=1;    }    return b;}int main(){    while(scanf("%d%d",&n,&m),n||m)    {        mat a(5,vec(5));        a[0][0]=0;a[0][1]=1;a[0][2]=0;a[0][3]=0;a[0][4]=0;        a[1][0]=1;a[1][1]=1;a[1][2]=1;a[1][3]=0;a[1][4]=1;        a[2][0]=0;a[2][1]=2;a[2][2]=1;a[2][3]=0;a[2][4]=0;        a[3][0]=0;a[3][1]=0;a[3][2]=0;a[3][3]=0;a[3][4]=1;        a[4][0]=0;a[4][1]=1;a[4][2]=0;a[4][3]=1;a[4][4]=0;        a=pow(a,n);        printf("%d\n",(a[0][0]+a[0][1]+a[0][2]*2+a[0][4])%m);    }    return 0;}

代码参考了网上的以为大牛,但是他的递推公式我有些不太明白,然后自己试着推了另外的一个公式,发现可以A。

a【0】代表第n行空

a【1】代表第n行满

a【2】代表第n行为0011或1100

a【3】代表第n行为1001

a【4】代表第n行为0110的情况

然后得到一系列的递推公式

使用矩阵快速幂即可求解

0 0
原创粉丝点击