110508 Pairsumonious Numbers


#include <iostream>
#include <vector>
#include <algorithm>
#include <math.h>

using namespace std;

static int FindNumber(const vector<int>& src, int target, int start, int end)
{
	if (end < start)
		return -1;

	int mid = (start + end) / 2;
	if (target == src[mid])
		return mid;
	if (target > src[mid])
		return FindNumber(src, target, mid + 1, end);
	return FindNumber(src, target, start, mid - 1);
}

static bool FoundAllLeftNumbers(int n, vector<int>& numbers, const vector<int>& sums)
{
	// The known numbers: X1, X2, X3
	// The known sums: sums[0] = X1 + X2, sums[1] = X1 + X3
	
	vector<int> otherSums(sums.begin() + 2, sums.end());
	int index = FindNumber(otherSums, numbers[1] + numbers[2], 0, otherSums.size() - 1); // Find X2 + X3.
	if (index < 0)
		return false;

	otherSums.erase(otherSums.begin() + index); // Now we also know the sum X2 + X3

	while(otherSums.size())
	{
		int nextNumber = otherSums[0] - numbers[0]; // To get X4, X5, ...
		if (nextNumber < numbers[numbers.size() - 1])
			break;

		otherSums.erase(otherSums.begin());
		int cnt = numbers.size();
		bool passed = true;
		for (int i = 1; i < cnt; ++i)
		{
			index = FindNumber(otherSums, numbers[i] + nextNumber, 0, otherSums.size() - 1);
			if (index < 0)
			{
				passed = false;
				break;
			}
			otherSums.erase(otherSums.begin() + index);
		}

		if (!passed)
			break;

		numbers.push_back(nextNumber);
	}

	if (otherSums.size() > 0)
	{
		int cnt = numbers.size();
		for (int i = 0; i < cnt - 3; ++i)
			numbers.pop_back(); // Remove the newly added numbers.
		return false;
	}

	return true;
}

static void FindNumbers(int n, vector<int>& sums)
{
	if (n <= 1)
	{
		cout << "Impossible" << endl;
		return;
	}

	if (n == 2)
	{
		cout << (sums[0] / 2) << ' ' << (sums[0] - (sums[0] / 2)) << endl;
		return;
	}

	sort(sums.begin(), sums.end());

	// ceil(sums[0] / 2.0) <= X2 <= floor(sums[n - 1] / 2.0)
	// X1 = sums[0] - X2
	// X3 = sums[1] - X1
	int lower = static_cast<int>(ceil(sums[0] / 2.0));
	int upper = static_cast<int>(floor(sums[n - 1] / 2.0));

	bool found = false;
	vector<int> numbers;
	for (int i = lower; i <= upper; ++i)
	{
		numbers.push_back(sums[0] - i); // X1
		numbers.push_back(i); // X2
		numbers.push_back(sums[1] - sums[0] + i); // X3

		if (FoundAllLeftNumbers(n, numbers, sums))
		{
			int cnt = numbers.size();
			for (int i = 0; i < cnt; ++i)
			{
				if (i != 0)
					cout << ' ';
				cout << numbers[i];
			}
			cout << endl;
			return;
		}

		numbers.pop_back();
		numbers.pop_back();
		numbers.pop_back();
	}

	cout << "Impossible" << endl;
}

static int GetSumsCnt(int n)
{
	return ((n - 1) * n) >> 1;
}

static void Test()
{
	int n, temp;
	vector<int> sums;
	while(cin >> n)
	{
		sums.clear();
		int cnt = GetSumsCnt(n);
		for (int i = 0; i < cnt; ++i)
		{
			cin >> temp;
			sums.push_back(temp);
		}
		FindNumbers(n, sums);
	}
}

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值