1. 程式人生 > >鋪地磚(找遞推式 + 大數)

鋪地磚(找遞推式 + 大數)

鋪地磚

時間限制: 1 Sec  記憶體限制: 128 MB

題目描述

一天,晨晨的數學老師佈置了一道題目,大意如下:用1×1和2×2的磁磚不重疊地鋪滿n×3的地板,共有多少種方案?
例如:n=1時:1×3的地板方法就一個,直接由三個1×1的磁磚鋪滿。
      n=2時:2×3的地板可以由下面3種方案鋪滿:

 

輸入

第一行:一個整數n(1≤n≤100)。

 

輸出

輸出鋪滿n×3的地板的方案數。

 

樣例輸入

複製樣例資料

3

樣例輸出

5

 

提示

對於20%的資料,1≤n≤15;
對於50%的資料,1≤n≤30;
對於100%的資料,1≤n≤100;

 

設寬為n的時候方案數為f[n];

根據這張圖可以發現,寬為2,長為3的有3種方法。由於長是固定為3的,那麼當寬大於2的時候,可以試著找

通過n-1,n-2的寬度來找,去掉n-1行,那麼就剩下最後一行,只能鋪1*1的磚3塊,所以為f[n-1];去掉n-2行,那麼還剩下兩行,也就只有上面三種方法,是3種嗎,看方法三,和去掉n-1行重複了,所以只有2種方法為2*f[n-2];

所以總共f[n]=f[n-1]+2*f[n-2];

由於資料太大,用大數做。

/**/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>

typedef long long LL;
using namespace std;

int f[105][10005];
int n;

void solve(int a[], int b[], int c[]){
	for (int i = 1; i <= b[0]; i++){
		a[i] += 2 * b[i];
		if(a[i] > 9){
			a[i + 1] += a[i] / 10;
			a[i] %= 10;
		}
	}
	int len = b[0];
	while(a[len + 1]) len++;
	for (int i = 1; i <= c[0]; i++){
		a[i] += c[i];
		if(a[i] > 9){
			a[i + 1]++;
			a[i] -= 10;
		}
	}
	int cnt = c[0];
	while(a[cnt + 1]){
		if(a[cnt + 1] > 9){
			a[cnt + 2]++;
			a[cnt + 1] -= 10;
			cnt++;
		}else{
			cnt++;
			break;
		}
	}
	a[0] = max(cnt, len);
}

int main()
{
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);

	scanf("%d", &n);
	f[1][0] = 1, f[1][1] = 1, f[2][0] = 1, f[2][1] = 3;
	for (int i = 3; i <= n; i++){
		solve(f[i], f[i - 2], f[i - 1]);
	}
	for (int i = f[n][0]; i >= 1; i--) printf("%d", f[n][i]);
	printf("\n");

	return 0;
}
/**/