P5303 逼死强迫症
P5303 逼死强迫症
题目描述
用足够多的
比如
分析
- 很明显要推导出递推式,那么我们定义
f[i] 为N=i 时的方案数量。
-
在
f[i-1] 的矩形的右边竖着放置一个1*2 的方块,则f[i]+=f[i-1] 。 -
在
f[i-2] 的矩形的右边横着放置两个2*2 的方块,则f[i]+=f[i-2] 。 -
当添加的一行填有
1*1 的方块(这里讨论1*1 的方块在右上角,右下角同理)。-
由于
1*1 方块上下不能与另一个1*1 方块相邻,所以这三个方块是固定的。 -
另一个
1*1 方块(称作小蓝)可以放在下方或上方,我们发现对于每一个位置,小蓝右边区域的放置方案是固定的,小蓝左边区域只需要使用1*2 的方块进行填充。 -
对于每一个
0<=k<=i-3 值计算方案数,此处定义p[k] 为2*k 的矩形中填充1*2 方块的方案数。则f[i]+=2*\sum\limits_{k=0}^{i-3}p[k] 。 -
可以发现
p[k]=p[k-1]+p[k-2] ,即斐波那契额数列。 -
斐波那契数列的前缀和满足
sum[n]=p[n+2]-1 ,证明如下sum[n]=p[1]+p[2]+p[3]+...+p[n] sum[n]=1+p[1]+p[2]+p[3]+...+p[n]-1 \because p[2]=1 \therefore sum[n]=(p[2]+p[1])+p[2]+p[3]+...+p[n]-1 sum[n]=(p[3]+p[2])+p[3]+...+p[n]-1 sum[n]=(p[n]+p[n-1])+p[n]-1 sum[n]=p[n+2]-1 -
所以
2*\sum\limits_{k=0}^{i-3}p[k]=2*sum[i-3]=2*p[i-1]-2 。
-
-
综上,我们得到的递推式是
f[i]=f[i-1]+f[i-2]+2*p[i-1]-2 ,观察数据范围,暴力递推是不现实的,所以需要使用矩阵幂进行维护。 -
我们要求一个矩阵
S ,使得:\begin{bmatrix} f[i-1] & f[i-2] & p[i-1] & p[i-2] & 1 \end{bmatrix}*S=\begin{bmatrix} f[i] & f[i-1] & p[i]& p[i-1] & 1 \end{bmatrix} 。得到:
S=\begin{bmatrix} 1 & 1 & 0 & 0 & \\ 1 & 0 & 0 & 0 & \\ 2 & 0 & 1 & 0 & \\ 0 & 0 & 1 & 0 & \\ -2 & 0 & 0 & 1 & \end{bmatrix} ,读者可以带入尝试。 -
由此可以推导出:
\begin{bmatrix} f[2] & f[1] & p[2] & p[1] & 1 \end{bmatrix}*S^{n-1}=\begin{bmatrix} f[n+1] & f[n] & p[n+1] & p[n] & 1 \end{bmatrix} ,答案便是得到矩阵的第一行第二列。 -
使用矩阵快速幂求得
S^{n-1} 。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=10,p=1e9+7;
int t;
struct matrix
{
int m[N][N];
}a,s,ans;
matrix operator * (const matrix& x,const matrix& y) //重载矩阵乘法
{
matrix c;
memset(c.m,0,sizeof(c.m));
for(int i=1;i<N;i++)
for(int j=1;j<N;j++)
for(int k=1;k<N;k++)
c.m[i][j]=(c.m[i][j]+x.m[i][k]*y.m[k][j])%p;
return c;
}
matrix pow_matrix(matrix x,int k) //矩阵快速幂
{
matrix c;
memset(c.m,0,sizeof(c.m));
for(int i=1;i<N;i++)c.m[i][i]=1;
while(k)
{
if(k&1)c=c*x;
k>>=1;
x=x*x;
}
return c;
}
signed main()
{
cin>>t;
while(t--)
{
int n;
cin>>n;
a.m[1][1]=0,a.m[1][2]=0,a.m[1][3]=2,a.m[1][4]=1,a.m[1][5]=1;
s.m[1][1]=1,s.m[1][2]=1,s.m[2][1]=1;
s.m[3][1]=2,s.m[3][3]=1,s.m[3][4]=1;
s.m[4][3]=1,s.m[5][1]=p-2,s.m[5][5]=1;
ans=a*pow_matrix(s,n-1);
cout<<ans.m[1][2]<<endl;
}
return 0;
}
其他
- 原题链接:https://www.luogu.com.cn/problem/P5303
- 博客链接:http:/218.201.91.220:8000/2024/07/18/...
- 洛谷专栏:https://www.luogu.com.cn/article/t2lwgbqq