算法实验选做1——POJ2506 Tiling

题目链接

题目大意:

求用 2 × 1 和 2 × 2 的瓷砖构成 2 × n 的长方形的种数。

思路: 

        明显的递归:a_n = 2a_{n - 1}+a_{n-2},可以用三个变量辗转递推节省空间。这道题的关键其实在于高精度,相当于一道高精度模板题。

AC代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string.h>
using std::cout;
class BN {
public:
	int* num;
	int length;
	BN(int len) :num(new int[len]), length(num ? len : 0) {
		for (int i = length - 1; i >= 0; i--) {
			num[i] = 0;
		}
	}
	BN(const char* const s) :num(new int[strlen(s)]), length(num ? strlen(s) : 0) {
		for (int i = length - 1; i >= 0; i--) {
			num[i] = s[i] - '0';
		}
	}
	~BN() {
		delete[] num;
		num = 0;
	}
	BN& operator=(const BN& bn);
	BN  operator+ (const BN& add);
	void Print() {
		int i = length - 1;
		while (i >= 0 && num[i] == 0) {
			i--;
		}
		while (i >= 0) {
			printf("%d", num[i]);
			i--;
		}
		printf("\n");
	}
};
BN& BN::operator=(const BN& bn) {
	if (num) delete num;
	num = new int[bn.length];
	this->length = num ? bn.length : 0;
	//printf("length:%d\n", length);
	for (int i = 0; i < length; i++) {
		num[i] = bn.num[i];
	}
	return *this;
}
BN BN:: operator+ (const BN& add) {
	int len = 1 + ((this->length > add.length) ? this->length : add.length);
	BN res(len);

	int carry = 0;
	for (int i = 0; i < len - 1; i++) {
		if (i >= this->length) {
			res.num[i] = (carry + add.num[i]) % 10;
			carry = (carry + add.num[i]) / 10;
		}
		else if (i >= add.length) {
			res.num[i] = (carry + this->num[i]) % 10;
			carry = (carry + this->num[i]) / 10;
		}
		else {
			res.num[i] = (carry + this->num[i] + add.num[i]) % 10;
			carry = (carry + this->num[i] + add.num[i]) / 10;
		}

	}
	if (carry != 0) res.num[len - 1] = carry;
	else {
		res.length--;
	}
	while (res.length >= 1 && res.num[res.length - 1] == 0) {
		res.length--;
	}
	return res;
}
int main() {
	int n;
	BN a1o("1"), a2o("3"), a3o(1);
	BN a1("1"), a2("3"), a3(1);
	a1 = a1o;
	a2 = a2o;
	a3 = a3o;


	while ((scanf("%d", &n) != EOF)) {
		a1 = a1o;
		a2 = a2o;
		if (n == 0) {
			printf("1\n");
		}
		else if (n == 1) {
			a1.Print();
		}
		else if (n == 2) {
			a2.Print();
		}
		else {
			for (int i = 3; i <= n; i++) {
				a3 = a2 + a1 + a1;
				//a3.Print();
				//a1.Print();
				//a3.Print(); cout << " = "; a2.Print(); cout << " + 2 * "; a1.Print();
				a1 = a2;
				a2 = a3;
			}
			a3.Print();
		}
	}


	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值