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;
}