110602 How Many Pieces of Land


// Max =  1 + C(n, 2) + C(n, 4)
// Refer to http://en.wikipedia.org/wiki/Dividing_a_circle_into_areas or  
// http://www.arbelos.co.uk/Papers/Chords-regions.pdf 

#include <vector>
#include <iostream>
#include <string.h>

using namespace std;

class Integer
{
public:
	Integer(char* buf, int len)
	{
		for (int i = 0; i < len; ++i)
			m_data.push_back(buf[i] - '0');
	}

	Integer() {}

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

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

		for (int i = 0; i < cnt; ++i)
			cout << m_data[i];
	}

	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 / 10;
			result.m_data.push_back(sum % 10);
			++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 += 10;
			}
			else
				flag = 0;
			result.m_data.push_back(left);
			++i;
		}
		if (flag < 0)
			result.m_data.push_back(9);

		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 / 10;
			result.m_data.push_back(tmp % 10);
		}
		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;
		}
	}

private:
	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;
};

static void DoTest(char* data)
{
	if ((!data) || (data[0] == '\0'))
	{
		cout << 0 << endl;
		return;
	}

	if (data[1] == '\0')
	{
		int max = -1;

		if (data[0] == '0')
			max = 1;
		else if (data[1] == '1')
			max = 1;
		else if (data[2] == '2')
			max = 2;
		else if (data[3] == '3')
			max = 8;

		if (max > 0)
		{
			cout << max << endl;
			return;
		}
	}

	Integer num(data, strlen(data));
	Integer one("1", 1);
	Integer two("2", 1);
	Integer three("3", 1);
	Integer four("4", 1);

	Integer result, tmpResult1, tmpResult2, tmpResult3, cn2, cn4;
	Integer numMinus1;
	num.Minus(one, numMinus1);
	num.Multiply(numMinus1, tmpResult1);
	tmpResult1.Divide(two, cn2); // Now we have C(n, 2)

	num.Minus(two, tmpResult1);
	cn2.Multiply(tmpResult1, tmpResult2);
	num.Minus(three, tmpResult1);
	tmpResult2.Multiply(tmpResult1, tmpResult3);
	tmpResult3.Divide(three, tmpResult2);
	tmpResult2.Divide(four, cn4);

	one.Add(cn2, tmpResult1);
	tmpResult1.Add(cn4, result);
	
	result.Print();
	cout << endl;
}

#define MAX_BUF_SIZE 4096

static void Test()
{
	int cnt;
	char buf[MAX_BUF_SIZE];
	cin >> cnt;
	for (int i = 0; i < cnt; ++i)
	{
		cin >> buf;
		DoTest(buf);
	}
}

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值