HDU 2604 Queuing

来源:互联网 发布:linux云计算视频教程 编辑:程序博客网 时间:2024/04/30 05:59


HDU2604: 本鶸第二道矩阵快速幂。

题意: 
n个人排队,f表示女,m表示男,包含子串fmf和fff为O队列,否则为E队列,求有多少个序列为E队列。

由于只求个数,按经验xjb找一下递推公式 :

用lm(n)表示n个人满足结果的个数,那么

1)如果最后一个是m,那么就不考虑他,lm(n)为前n-1的结果个数;

2)如果最后一个是f,并且是mmf,那么需要向前推3位,即lm(n-3);//不考虑fmf和fff

3)如果最后一个是f,并且是mff,那么需要再向前推一位到mmff才能满足结果,即lm(n-4);

所以lm(n)=lm(n-1)+lm(n-3)+lm(n-4)

不过题目提到要%M,猜一下无脑递推大概会TLE,按照1e17fibonacci的经验我们知道这个时候就需要矩阵加速来搞一下。

借一张神犇们的图说明一下矩阵的构造方法

矩阵和快速幂的知识可以参考这里

#include<cstdio>#include<cstring>struct matrix{    int s[4][4];    matrix()    {        memset(s,0,sizeof(s));    }};int n,mod,sq[4][4]={{0,0,0,1},{1,0,0,0},{1,1,0,0},{0,0,1,1}};void lm00(int *a,int *b){    for(int i=0;i<16;i++)        a[i]=b[i];}matrix mult(int a[][4],int b[][4]){    matrix c;    for(int i=0;i<4;i++)        for(int j=0;j<4;j++)        {            for(int k=0;k<4;k++)                c.s[i][j]=(c.s[i][j]+a[i][k]*b[k][j])%mod;        }        return c;}matrix lm(int m){    matrix a;    if(m==1)    {        lm00(&a.s[0][0],&sq[0][0]);    }    else    {        a=lm(m/2);        a=mult(a.s,a.s);        if(m&1)            a=mult(a.s,sq);    }    return a;}int main(){    int ans=0;    matrix s;    while(~scanf("%d%d",&n,&mod))    {        s=lm(n-2);        ans=0;        for(int i=0;i<4;i++)        {            for(int j=0;j<4;j++)            {                ans=(ans+s.s[i][j])%mod;            }        }        printf("%d\n",ans);    }    return 0;}

0 0
原创粉丝点击