题目描述
你有一个长为N宽为2的墙壁,给你两种砖头:一个长2宽1,另一个是L型覆盖3个单元的砖头。如下图:
0 0
0 00
砖头可以旋转,两种砖头可以无限制提供。你的任务是计算用这两种来覆盖N*2的墙壁的覆盖方法。例如一个2*3的墙可以有5种覆盖方法,如下:
012 002 011 001 011
012 112 022 011 001
注意可以使用两种砖头混合起来覆盖,如2*4的墙可以这样覆盖:
0112
0012
给定N,要求计算2*N的墙壁的覆盖方法。由于结果很大,所以只要求输出最后4位。例如2*13的覆盖方法为13465,只需输出3465即可。如果答案少于4位,就直接输出就可以,不用加0,如N=3,时输出5。
输入格式
一个整数N(1<=N<=1000000),表示墙壁的长。
输出格式
输出覆盖方法的最后4位,如果不足4位就输出整个答案。
输入输出样例
输入 #1
13
输出 #1
3465
这是一道练习递归/递推思想的一道超好的题目,用到了两个递推公式
分析:
- 首先记a[n]为填铺长度为n的墙壁可以采用的方法数,b[n]记为在第n个位置上,只有一半的墙壁已经贴好的方法数
- 首先可得状态转移方程:a[n]=a[n-1]+a[n-2]+2*b[n-1];
- 又可以得到b[n]=a[n-2]+b[n-1];
- 初始条件:a[1]=1,a[2]=2; b[1]=0,b[2]=1;
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int MAX = 1000005;
const int INF = 0x7fffffff;
int N;
int a[MAX],b[MAX];
int main() {
scanf("%d",&N);
a[1]=1,a[2]=2;
b[1]=0,b[2]=1;
for(int i=3;i<=N;i++) {
a[i]=(a[i-1]+a[i-2]+2*b[i-1])%10000;
b[i]=((a[i-2]+b[i-1]))%10000;
}
printf("%d\n",a[N]);
}