HDU2604:Queuing(矩阵快速幂+递推)

传送门

题意

长为len的字符串只由'f','m'构成,有2^len种情况,问在其中不包含'fmf','fff'的字符串有多少个,此处将队列换成字符串

分析

矩阵快速幂写的比较崩,手生了,多练!

用f(n)表示n个人满足条件的结果,那么如果最后一个人是m的话,那么前n-1个满足条件即可,就是f(n-1);
如果最后一个是f那么这个还无法推出结果,那么往前再考虑一位:那么后三位可能是:mmf, fmf, mff, fff,其中fff和fmf不满足题意所以我们不考虑,但是如果是
mmf的话那么前n-3可以找满足条件的即:f(n-3);如果是mff的话,再往前考虑一位的话只有mmff满足条件即:f(n-4)
所以f(n)=f(n-1)+f(n-3)+f(n-4),递推会跪,可用矩阵快速幂
构造一个矩阵:
tupian

代码

#include<cstdio>
#include<cstring>
using namespace std;

struct matrix
{
    int a[5][5];
    int row,col;
}ret,ans,tmp;
int n,mod;
matrix multi(matrix x,matrix y)
{
    matrix t;
    for(int i=1;i<=4;++i)for(int j=1;j<=4;++j)
    {
        t.a[i][j]=0;
        for(int k=1;k<=4;++k) (t.a[i][j]+=x.a[i][k]*y.a[k][j])%=mod;
    }
    //for(int i=1;i<=4;++i) printf("%d\n",t.a[i][1]);
    return t;
}
void fast_mod(int p)
{
    for(int i=1;i<=4;++i)for(int j=1;j<=4;++j)if(i==j) tmp.a[i][j]=1;else tmp.a[i][j]=0;
    ret.a[1][1]=1,ret.a[1][2]=0,ret.a[1][3]=1,ret.a[1][4]=1;
    ret.a[2][1]=1,ret.a[2][2]=0,ret.a[2][3]=0,ret.a[2][4]=0;
    ret.a[3][1]=0,ret.a[3][2]=1,ret.a[3][3]=0,ret.a[3][4]=0;
    ret.a[4][1]=0,ret.a[4][2]=0,ret.a[4][3]=1,ret.a[4][4]=0;
    //ret.col=ret.row=tmp.row=tmp.col=4;
    for(;p;p>>=1,ret=multi(ret,ret)) if(p&1) tmp=multi(tmp,ret);
}
int main()
{
    memset(ans.a,0,sizeof(ans.a));
    ans.row=4,ans.col=1;
    ans.a[1][1]=9;
    ans.a[2][1]=6;
    ans.a[3][1]=4;
    ans.a[4][1]=2;
    while(scanf("%d %d",&n,&mod)==2)
    {
        if(n==0) { puts("1");continue; }
        if(n<=4) {printf("%d\n",(ans.a[4-n+1][1])%mod);continue;}
        fast_mod(n-4);
       // for(int i=1;i<=4;++i) printf("%d\n",ans.a[i][1]);
        int q=9*tmp.a[1][1]+6*tmp.a[1][2]+4*tmp.a[1][3]+2*tmp.a[1][4];
        printf("%d\n",q%mod);
        //puts("2");
        //printf("%d\n",ans.a[1][1]);
    }
}
posted @ 2017-04-10 23:18  遗风忘语  阅读(291)  评论(0编辑  收藏  举报