1005継続(3 n+1)推定(25点)


1005継続(3 n+1)推定(25点)
カラズ(Callatz)推測は1001に記載されている.このテーマでは、状況が少し複雑です.
カラズの推測を検証すると,繰返し計算を避けるために,繰返し中に遭遇した各数を記録することができる.例えば、n=3を検証する場合、3、5、8、4、2、1を計算する必要があり、n=5、8、4、2を検証すると、繰り返し計算する必要がなく、カラズの推測の真偽を直接判定することができる.この4つの数はすでに検証3の時に遭遇したため、5、8、4、2は3によって「覆われた」数である.1つの数列のある数nを「キー数」と呼び、nが数列の他の数で上書きできない場合.
検証対象の一連の数値を指定すると、いくつかのキー数を検証するだけで、残りの数値を繰り返し検証する必要はありません.あなたの任務は、これらの重要な数字を見つけて、大きな順に出力することです.
入力形式:
各試験入力は1つの試験例を含み、1行目は正の整数K(<100)を与え、2行目はK個の互いに異なる検証される正の整数n(1)を与える.
出力フォーマット:
各テスト・インスタンスの出力は1行を占め、キー数は大きい順に出力されます.数字の間は1つのスペースで区切られていますが、1行の最後の数字の後にはスペースがありません.
サンプルを入力:
6
3 5 6 7 8 11

出力サンプル:
7 6

解題構想:大きな配列arr(長さ10000)を用い,初期はfalseであった.n=3で検証する場合,3,5,8,4,2,1を計算する必要があり,配列中のarr[5]=trueは上書きされることを示す.同様に、arr[8]=true、arr[4]=true、arr[2]=trueも上書きされることを表す.配列を遍歴し、arr[i]=falseであればキー数となる.
実装コード:
#include
#include
#include
#define MAX 10000
using namespace std;
bool num[3 * MAX + 1];
int main(void) {
	int n, data;
	vector v;
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> data;
		v.push_back(data);
		while (data != 1) {
			if (data % 2)
				data = (3 * data + 1) / 2;
			else
				data /= 2;
			num[data] = true;
		}
	}
	sort(v.begin(), v.end());
	reverse(v.begin(), v.end());
	int flag = 0;
	for (int i = 0; i < v.size(); i++)
		if (num[v[i]] == false) {
			if (flag)
				cout << " ";
			cout << v[i];
			flag = 1;
		}
}