P5303 题解
题意简述
题目分析
注意到
我们很自然地想到使用
显然,
- 使用一块竖着的
的砖。
显然铺满的种类就是左边
- 使用两块横着的
的砖。
铺满的种类就是左边
- 使用
的砖。
很明显这块砖可以摆在上下两种位置。以摆在上面为例,那么由于两块
注意到使用另一块
设
经过上文类似的讨论可以得到
回到原题,由于
综上,有递推公式
我们对转移矩阵一列一列地来解释。
对于第一列,有
对于第二列,有
对于第三列,有
对于第四列,有
对于第五列,有
现在我们只需要计算出转移矩阵的
需要注意的是要特判
分析一下时间复杂度。一次矩阵乘法是
代码实现
#include<bits/stdc++.h> using namespace std; const int mod=1000000007; int t,n; struct matrix { int n,m; int a[6][6]; void init(int k) { for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(i!=j) a[i][j]=0; else a[i][j]=k; }//初始化矩阵,k=0是零矩阵,k=1为单位矩阵 friend matrix operator *(matrix a,matrix b) { matrix c; c.n=a.n,c.m=b.m; c.init(0); for(int i=1;i<=c.n;i++) for(int j=1;j<=c.m;j++) for(int k=1;k<=b.n;k++) (c.a[i][j]+=1ll*a.a[i][k]*b.a[k][j]%mod)%=mod; return c; }//矩阵乘法 friend matrix operator ^(matrix a,int b) { matrix c; c.n=c.m=a.n; c.init(1); for(;b;b>>=1) { if(b&1) c=c*a; a=a*a; } return c; }//矩阵快速幂 }fs,tr; int main() { scanf("%d",&t); while(t--) { scanf("%d",&n); if(n<=2)//特判 { printf("0\n"); continue; } fs.n=1,fs.m=tr.n=tr.m=5; fs.init(0); fs.a[1][5]=fs.a[1][4]=1; fs.a[1][1]=fs.a[1][3]=2;//答案矩阵初始化 tr.init(0); tr.a[1][1]=tr.a[2][1]=tr.a[1][2]=tr.a[3][3]=tr.a[4][3]=tr.a[4][4]=tr.a[4][5]=tr.a[5][3]=tr.a[5][4]=1; tr.a[3][1]=2;//转移矩阵初始化 tr=tr^(n-3); fs=fs*tr; printf("%d\n",fs.a[1][1]); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下