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 ",ans); } return 0; }