10359 - Tiling (递推,类斐波那契)

Problem G

Tiling

Input: standard input

Output: standard output

Time Limit: 2 seconds

Memory Limit: 32 MB

 

In how many ways can you tile a 2xn rectangle by 2x1 or 2x2 tiles?

Here is a sample tiling of a 2x17 rectangle.

Input and Output

Input is a sequence of lines, each line containing an integer number 0 <= n <= 250. For each line of input, output one integer number in a separate line giving the number of possible tilings of a 2xn rectangle.

Sample Input

2
8
12
100

200

Sample Output

3
171
2731
845100400152152934331135470251
1071292029505993517027974728227441735014801995855195223534251
题意:给定2*1 和 2*2的小块,要求拼接成2 * n有多少种方法。

思路:假设当前块为2 * 1 剩下为 f(n - 1)种,当前为2*2,剩下为f(n - 1)种,2*2有2种组合方法。所以f(n) = f(n - 1) + f(n - 2) * 2;

代码:

#include <stdio.h>
#include <string.h>
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
const int N = 2222;
const int MAXBIGN = 305;


struct bign {
    int s[MAXBIGN];
    int len;
    bign() {
		len = 1;
		memset(s, 0, sizeof(s));
    }
	
    bign operator = (const char *number) {
		len = strlen(number);
		for (int i = 0; i < len; i++)
			s[len - i - 1] = number[i] - '0';
		return *this;
    }
    bign operator = (const int num) {
		char number[N];
		sprintf(number, "%d", num);
		*this = number;
		return *this;
    }
	
    bign (int number) {*this = number;}
    bign (const char* number) {*this = number;}
	
    bign operator + (const bign &c){  
		bign sum;
		int t = 0;
		sum.len = max(this->len, c.len);
		for (int i = 0; i < sum.len; i++) {
			if (i < this->len) t += this->s[i];
			if (i < c.len) t += c.s[i];
			sum.s[i] = t % 10;
			t /= 10;
		}
		
		while (t) {
			sum.s[sum.len++] = t % 10;
			t /= 10;
		}
		
		return sum;  
    }
	
	bign operator * (const bign &c){  
		bign sum; bign zero;
		if (*this == zero || c == zero)
			return zero;
		int i, j;
		sum.len = this->len + c.len;
		for (i = 0; i < this->len; i++) {
			for (j = 0; j < c.len; j ++) {
				sum.s[i + j] += this->s[i] * c.s[j];
			}
		}
		for (i = 0; i < sum.len; i ++) {
			sum.s[i + 1] += sum.s[i] / 10;
			sum.s[i] %= 10;
		}
		sum.len ++;
		while (!sum.s[sum.len - 1]) {
			sum.len --;
		}
		return sum;  
    }	
    bign operator - (const bign &c) {
		bign ans;
		ans.len = max(this->len, c.len);
		int i;
		
		for (i = 0; i < c.len; i++) {
			if (this->s[i] < c.s[i]) {
				this->s[i] += 10;
				this->s[i + 1]--;
			}
			ans.s[i] = this->s[i] - c.s[i];
		}
		
		for (; i < this->len; i++) {
			if (this->s[i] < 0) {
				this->s[i] += 10;
				this->s[i + 1]--;
			}
			ans.s[i] = this->s[i];
		}
		while (ans.s[ans.len - 1] == 0) {
			ans.len--;
		}
		if (ans.len == 0) ans.len = 1;
		return ans;
    }
	
    void put() {
		if (len == 1 && s[0] == 0) {
			printf("0");
		} else {
			for (int i = len - 1; i >= 0; i--)
				printf("%d", s[i]);
		}
    }
	
    bool operator < (const bign& b) const {
		if (len != b.len)
			return len < b.len;
		
		for (int i = len - 1; i >= 0; i--)
			if (s[i] != b.s[i])
				return s[i] < b.s[i];
			return false;
    }
    bool operator > (const bign& b) const { return b < *this; }
    bool operator <= (const bign& b) const { return !(b < *this); }
    bool operator >= (const bign& b) const { return !(*this < b); }
    bool operator != (const bign& b) const { return b < *this || *this < b;}
    bool operator == (const bign& b) const { return !(b != *this); }
};
int n;
bign save[255];

void init() {
	save[0] = 1; save[1] = 1; bign tep = 2;
	for (int i = 2; i <= 250; i ++) {
		save[i] = save[i - 1] + (save[i - 2] * tep);
	}
}

int main() {
	init();
	while (~scanf("%d", &n)) {
		save[n].put();
		printf("\n");
	}
	return 0;
}



你可能感兴趣的:(10359 - Tiling (递推,类斐波那契))