110604 Expressions


#include <vector>
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <string>
#include <stdlib.h>

using namespace std;

static const int STEP = 4;
static const int UNIT = pow(10, STEP);

class Integer
{
public:
	Integer(char* buf, int len)
	{
		int first = len % STEP;
		if (first > 0)
		{
			int x = 0;
			for (int j = 0; j < first; ++j)
			{
				x = x * 10 + buf[j] - '0';
			}
			m_data.push_back(x);
		}

		buf += first;
		len -= first;
		for (int i = 1; i <= len/STEP; ++i)
		{
			int x = 0;
			for (int j = 0; j < STEP; ++j)
			{
				x = x * 10 + buf[(i - 1) * STEP + j] - '0';
			}
			m_data.push_back(x);
		}
	}

	Integer() {}

	void Print()
	{
		int cnt = m_data.size();

		if (cnt <= 0)
			cout << "0";

		string format("%0xd");
		format[2] = STEP + '0';
		for (int i = 0; i < cnt; ++i)
		{
			if (i == 0)
				cout << m_data[i];
			else
				printf(format.c_str(), m_data[i]);
		}
	}

public:
	void Add(const Integer& other)
	{
		Integer result;
		Add(other, result);
		m_data = result.m_data;
	}

	void Multiply(const Integer& other)
	{
		Integer result;
		Multiply(other, result);
		m_data = result.m_data;
	}

private:
	void Add(const Integer& other, Integer& result) const
	{
		result.m_data.clear();
		int flag = 0;
		int i = 0, limit = (other.m_data.size() > m_data.size()) ? other.m_data.size() : m_data.size();
		while(i < limit)
		{
			int num1 = (i < m_data.size()) ? m_data[m_data.size() - 1 - i] : 0;
			int num2 = (i < other.m_data.size()) ? other.m_data[other.m_data.size() - 1 - i] : 0;
			int sum = num1 + num2 + flag;
			flag = sum / UNIT;
			result.m_data.push_back(sum % UNIT);
			++i;
		}
		if (flag > 0)
			result.m_data.push_back(flag);

		result.ShrinkAndInvert();
	}

	void Minus(const Integer& other, Integer& result) const
	{
		result.m_data.clear();
		int flag = 0;
		int i = 0, limit = (other.m_data.size() > m_data.size()) ? other.m_data.size() : m_data.size();
		while(i < limit)
		{
			int num1 = (i < m_data.size()) ? m_data[m_data.size() - 1 - i] : 0;
			int num2 = (i < other.m_data.size()) ? other.m_data[other.m_data.size() - 1 - i] : 0;
			int left = num1 - flag - num2;
			if (left < 0)
			{
				flag = 1;
				left += UNIT;
			}
			else
				flag = 0;
			result.m_data.push_back(left);
			++i;
		}
		if (flag < 0)
			result.m_data.push_back(UNIT - 1);

		result.ShrinkAndInvert();
	}

	void Multiply(const Integer& other, Integer& result) const
	{
		result.m_data.clear();
		for (int i = other.m_data.size() - 1; i >= 0; --i)
		{
			Integer tmp, sum;
			Multiply(other.m_data[i], tmp, other.m_data.size() - i - 1);
			result.Add(tmp, sum);
			result = sum;
		}
	}

	void Multiply(const int n, Integer& result, int shift) const
	{
		result.m_data.clear();
		for (int i = 0; i < shift; ++i)
			result.m_data.push_back(0);

		int flag = 0;
		for (int i = m_data.size() - 1; i >= 0; --i)
		{
			int tmp = m_data[i] * n + flag;
			flag = tmp / UNIT;
			result.m_data.push_back(tmp % UNIT);
		}
		if (flag > 0)
			result.m_data.push_back(flag);

		result.ShrinkAndInvert();
	}

	void Divide(const Integer& other, Integer& result) const
	{
		result.m_data.clear();
		if (operator == (other))
		{
			result.m_data.push_back(1);
			return;
		}

		if (!(operator > (other)))
			return;

		int sizeDev = m_data.size() - other.m_data.size();
		Integer tmp = (*this);
		Integer resultTmp1, resultTmp2;
		for (int i = sizeDev; i >= 0; --i)
		{
			Integer tmp1, tmp2;
			other.Multiply(1, tmp1, i);
			int sum = 0;
			while(true)
			{
				if (tmp >= tmp1)
				{
					tmp.Minus(tmp1, tmp2);
					++sum;
					tmp = tmp2;
				}
				else
					break;
			}
			resultTmp1.m_data.clear();
			if (sum > 0)
			{
				for (int j = 0; j < i; ++j)
					resultTmp1.m_data.push_back(0);
				resultTmp1.m_data.push_back(sum);
				resultTmp1.ShrinkAndInvert();
			}
			result.Add(resultTmp1, resultTmp2);
			result = resultTmp2;
		}
	}

	void ShrinkAndInvert()
	{
		while(m_data.size() != 0)
		{
			if (m_data[m_data.size() - 1] == 0)
				m_data.pop_back();
			else
				break;
		}

		int cnt = m_data.size();
		for (int i = 0; i < cnt / 2; ++i)
		{
			int tmp = m_data[i];
			m_data[i] = m_data[cnt - 1 - i];
			m_data[cnt - 1 - i] = tmp;
		}
	}

	bool operator > (const Integer& other) const
	{
		if (m_data.size() > other.m_data.size())
			return true;
		if (m_data.size() < other.m_data.size())
			return false;
		for (int i = 0; i < m_data.size(); ++i)
			if (m_data[i] < other.m_data[i])
				return false;
			else if (m_data[i] > other.m_data[i])
				return true;
		return false;
	}

	bool operator == (const Integer& other) const
	{
		if (m_data.size() != other.m_data.size())
			return false;
		for (int i = 0; i < m_data.size(); ++i)
			if (m_data[i] != other.m_data[i])
				return false;
		return true;
	}

	bool operator >= (const Integer& other) const
	{
		return ((operator > (other)) || (operator == (other)));
	}

private:
	vector<int> m_data;
};

#define MAX_PAIRS 150
#define MAX_DEPTH 150

static Integer s_Zero("0", 1);
static Integer s_One("1", 1);

typedef Integer* IntegerPtr;

static IntegerPtr** InitResults()
{
	IntegerPtr** results = new IntegerPtr* [MAX_PAIRS + 1];
	for (int i = 0; i <= MAX_PAIRS; ++i)
	{
		results[i] = (IntegerPtr*)calloc(i + 1, sizeof(IntegerPtr));
		if (i == 0)
			results[0][0] = &s_One;
		else
		{
			results[i][0] = &s_Zero;
			results[i][1] = &s_One;
			results[i][i] = &s_One;
		}
	}
	return results;
}

static void DeleteResults(IntegerPtr** results)
{
	for (int i = 0; i <= MAX_PAIRS; ++i)
	{
		for (int j = 0; j <= i; ++j)
		{
			IntegerPtr pResult = results[i][j];
			if ((pResult != (&s_Zero)) &&
				(pResult != (&s_One)))
				delete pResult;
		}
		free(results[i]);
	}
	delete[] results;
}

static IntegerPtr** InitSumsByDepth()
{
	IntegerPtr** sumsByDepth = new IntegerPtr* [MAX_PAIRS + 1];
	for (int i = 0; i <= MAX_PAIRS; ++i)
	{
		sumsByDepth[i] = (IntegerPtr*)calloc(i + 1, sizeof(IntegerPtr));
		if (i == 0)
			sumsByDepth[0][0] = &s_One;
		else
		{
			sumsByDepth[i][0] = &s_Zero;
			sumsByDepth[i][1] = &s_One;
		}
	}
	return sumsByDepth;
}

static void DeleteSumsByDepth(IntegerPtr** sumsByDepth)
{
	for (int i = 0; i <= MAX_PAIRS; ++i)
	{
		for (int j = 0; j <= i; ++j)
		{
			IntegerPtr pResult = sumsByDepth[i][j];
			if ((pResult != (&s_Zero)) &&
				(pResult != (&s_One)))
				delete pResult;
		}
		free(sumsByDepth[i]);
	}
	delete[] sumsByDepth;
}

static IntegerPtr GetResult(int pairs, int depth, IntegerPtr** results, IntegerPtr** sumsByDepth);

static IntegerPtr GetSumsByDepth(
	int pairs, int depth, IntegerPtr** results, IntegerPtr** sumsByDepth)
{
	if (depth > pairs)
		depth = pairs;

	if (sumsByDepth[pairs][depth] != NULL)
		return sumsByDepth[pairs][depth];

	IntegerPtr result = new Integer("0", 1);
	result->Add(*GetSumsByDepth(pairs, depth - 1, results, sumsByDepth));
	if (depth <= pairs)
	{
		if (depth == pairs)
			result->Add(s_One);
		else
			result->Add(*GetResult(pairs, depth, results, sumsByDepth));
	}
	sumsByDepth[pairs][depth] = result;
	return result;
}

static IntegerPtr GetResult(int pairs, int depth, IntegerPtr** results, IntegerPtr** sumsByDepth)
{
	if (depth > pairs)
		return &s_Zero;

	if (depth == pairs)
		return &s_One;

	if (results[pairs][depth] != NULL)
		return results[pairs][depth];

	// F(n,d): How many legal combinations for n pairs of brackets with depth as d.
	// F(n,d) = Sum(k = 0 to n-1){ F(k,d-1)*Sum(i = 0 to d){F(n-k-1,i)} + F(n-k-1, d)*Sum(i = 0 to d-2){F(k,i)} }
	IntegerPtr finalResult = new Integer("0", 1);
	for (int k = 0; k <= pairs - 1; ++k)
	{
		if (depth - 1 <= k)
		{
			Integer tempResult("0", 1);
			tempResult.Add(*GetSumsByDepth(pairs - k - 1, depth, results, sumsByDepth));

			if ((depth != 2) && (depth != (k + 1)))
				tempResult.Multiply(*GetResult(k, depth - 1, results, sumsByDepth));

			finalResult->Add(tempResult);
		}

		if (depth <= (pairs - k - 1))
		{
			Integer tempResult("0", 1);
			tempResult.Add(*GetSumsByDepth(k, depth - 2, results, sumsByDepth));

			if ((depth != 1) && (depth != (pairs - k - 1)))
				tempResult.Multiply(*GetResult(pairs - k - 1, depth, results, sumsByDepth));

			finalResult->Add(tempResult);
		}
	}

	results[pairs][depth] = finalResult;
	return finalResult;
}

static void DoTest(int n, int d, IntegerPtr** results, IntegerPtr** sumsByDepth)
{
	if (((n % 2) != 0) || (d > (n/2)))
	{
		cout << '0';
		return;
	}

	if ((d == (n/2)) || (d == 1))
	{
		cout << '1';
		return;
	}

	IntegerPtr result = GetResult(n/2, d, results, sumsByDepth);
	result->Print();
}

static void Test()
{
	IntegerPtr** results = InitResults();
	IntegerPtr** sumsByDepth = InitSumsByDepth();

	int n, d;
	while (cin >> n >> d)
	{
		DoTest(n, d, results, sumsByDepth);
		cout << endl;
	}

	DeleteResults(results);
	DeleteSumsByDepth(sumsByDepth);
}

int main(int argc, char* argv[])
{
	Test();
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值