題目描述
你有一個長爲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]);
}