先来看我的第一种思路

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 1000000 + 7;

int Q[MAXN * 2 + 2];
int arr[MAXN * 2 + 2];

int main()
{
	int a, n;
	while(cin >> a >> n)
	{
		Q[0] = a;
		for(int i=0; i<=n; i++)
		{
			Q[i*2+1] = Q[i] * 2 + 1;	// 左子树
			Q[i*2+2] = Q[i] * 3 + 1;	// 右子树
		}
		sort(Q, Q+ n*2+3);		// 排序
		int cnt = 0;
		arr[0] = Q[0];
		for(int i=0; i<=n*2 +2; i++)		// 去重
		{
			if(arr[cnt] != Q[i])
				arr[++cnt] = Q[i];
		}
		cout << arr[n-1] << endl;			// 输出第n个元素
	}

	return 0;
}

第一种思路是建立一个二叉树,因为每个节点都会衍生出另外两个结点,分别是2x+1 和 3x+1,这符合二叉树的特性

因此建立的是一个线性的二叉树

根节点 Q[0]

左子树 i * 2 + 1             右子树 i * 2 + 2

因为这样建立起来,线性数组中并不是升序排列

所以sort排序一下

此外在建立的过程中可能有相同值的结点,所以在排序后需要去重。

这些都完成后,去重后的数组中第 n - 1 个元素,就是要输出的第 n 个值。

但是,这样做并不对,当测试数据较小的时候是没问题的,当测试数据较大是就会出现实际输出的值比理论值大的情况。

至于BUG在哪里我暂时还没有发现。 

 

接下来是另一个思路,直接看代码吧,有详细注释。

#include <iostream>
using namespace std;
const int MAXN = (int) 1e6 + 7;

int Q[MAXN];
int main()
{
	int a, n;
	int two, three, rear;
	while(cin >> a >> n)
	{
		Q[0] = a;			// 基
		two = three = rear = 0;		// 初始下标为0
		int tmp, tmp1, tmp2;
		while(rear < n)
		{
//			分析:
//			从第一个数开始,每个数都会衍生出两个数,分别是 2x+1 和 3x+1
//			我们不是每次都把同一个数衍生出的两个数都求出来
//			而是错开
//			即可以不同时的取最多两个数中的一个 2x+1 另一个取 3x+1
//			每次取这两者中较小的一个
//			然后较小的这个数的原型 x 就的一个衍生数 2x+1 或 3x+1 就已经取过了
//			所以就会有 two++ 或 three++
 			tmp1 = Q[two] * 2 + 1;
			tmp2 = Q[three] * 3 + 1;
			tmp = min(tmp1, tmp2);		// 取较小的一个
			tmp1 < tmp2 ? two ++ : three ++;
			if(Q[rear] != tmp)	// 不是重复出现的元素就加入
				Q[++rear] = tmp;
		}
		cout << Q[n-1] << endl;
	}





	return 0;
}