概述
这是一道典型的递推题型,代码量简短,本文主要分析一下递推公式。(本菜菜什么时候看到这种递推题目能快速的公式啊)
题目来源
https://www.luogu.com.cn/problem/P1990
点击查看题目
# 覆盖墙壁
## 题目描述
你有一个长为 $N$ 宽为 $2$ 的墙壁,给你两种砖头:一个长 $2$ 宽 $1$,另一个是 L 型覆盖 $3$ 个单元的砖头。如下图:
0 0
0 00
砖头可以旋转,两种砖头可以无限制提供。你的任务是计算用这两种来覆盖 $N\times 2$ 的墙壁的覆盖方法。例如一个 $2\times3$ 的墙可以有 $5$ 种覆盖方法,如下:
012 002 011 001 011
012 112 022 011 001
注意可以使用两种砖头混合起来覆盖,如 $2\times4$ 的墙可以这样覆盖:
0112
0012
给定 $N$,要求计算 $2\times N$ 的墙壁的覆盖方法。由于结果很大,所以只要求输出最后 $4$ 位。例如 $2\times 13$ 的覆盖方法为 $13465$,只需输出 $3465$ 即可。如果答案少于 $4$ 位,就直接输出就可以,不用加前导 $0$,如 $N=3$ 时输出 $5$。
## 输入格式
一个整数 $N$,表示墙壁的长。
## 输出格式
输出覆盖方法的最后 $4$ 位,如果不足 $4$ 位就输出整个答案。
## 样例 #1
### 样例输入 #1
13
### 样例输出 #1
3465
## 提示
数据保证,$1\leq N\leq 1000000$。
递推公式
设覆盖n*2的墙需要f[n]个砖,当n=0时,表示不需要砖,此时方案数为1,即f[0]=1;当n<0时没有意义
-
当最后一列放一个2*1的砖块,这种情况数显然是f[n-1]。
![]()
-
当最后两列是两个横着放的2*1砖块时,这种情况显然是f[n-2]。
![]()
-
最后一种情况,也是最重要的情况,就是最后是“L”型的砖块时,可以发现只要放一个与之相对的“L"型砖块,就可以获得一个标准的长方形,这也是我们想要的,同时,可以发现,在这两个砖块之间可以加入任意对交替排列的2*1砖块,这种排列只有一种,所以第三种情况数是f[n-3]+f[n-4]+f[n-5]+...(另一种方向相对的"L"型砖块与这种情况相同,作为一种情况考虑。
![]()
-
最后的公式就是f[n]=f[n-1]+f[n-2]+2*(f[n-3]+f[n-4]+...+f[0]),公式是正确的,但是我们发现在所给的数据范围进行O(n²)的复杂度会超时,我们可以使用前缀和。那么最后的递推公式为:f[n]=pre[n-1]+pre[n-3]
实现代码
using namespace std;
int INT=10000;
int main(){
int n;
cin>>n;
int f[n+1]={0};
int pre[n+1]={0};
f[0]=1;f[1]=1;f[2]=2;
pre[0]=1;pre[1]=2;pre[2]=4;
for(int i=3;i<=n;i++){
f[i]=(pre[i-1]+pre[i-3])%INT;
pre[i]=(pre[i-1]+f[i])%INT;//更新前缀和
}
cout<<f[n]<<endl;
}



浙公网安备 33010602011771号