Polycarp likes to play with numbers. He takes some integer number x , writes it down on the board, and then performs with it n−1
operations of the two kinds:
After each operation, Polycarp writes down the result on the board and replaces x by the result. So there will be n numbers on the board after all.
You are given a sequence of length n — the numbers that Polycarp wrote down. This sequence is given in arbitrary order, i.e. the order of the sequence can mismatch the order of the numbers written on the board.
Your problem is to rearrange (reorder) elements of this sequence in such a way that it can match possible Polycarp’s game in the order of the numbers written on the board. I.e. each next number will be exactly two times of the previous number or exactly one third of previous number.
It is guaranteed that the answer exists.
Input
The first line of the input contatins an integer number n ( 2≤n≤100 ) — the number of the elements in the sequence. The second line of the input contains n integer numbers a1,a2,…,an ( 1≤ai≤3⋅1018 ) — rearranged (reordered) sequence that Polycarp can wrote down on the board.
Output
Print n integer numbers — rearranged (reordered) input sequence that can be the sequence that Polycarp could write down on the board.
It is guaranteed that the answer exists.
Examples
Input |
---|
6 4 8 6 3 12 9 |
Output |
9 3 6 12 4 8 |
Input |
---|
4 42 28 84 126 |
Output |
126 42 84 28 |
Input |
---|
2 1000000000000000000 3000000000000000000 |
Output |
3000000000000000000 1000000000000000000 |
Note
In the first example the given sequence can be rearranged in the following way: [9,3,6,12,4,8] . It can match possible Polycarp’s game which started with x=9 .
【题意】
有一个原始串 a[n] ,每一位都满足下列的其中一个条件
现在用打乱的顺序给出该串,输出原串。
【思路】
每个点有两种转移情况,而且转移不可逆,可以放到有向图上思考:给一个含有n个点,最多2*n条边的有向图,找出一条经过所有点的路径。暴力搜索一遍表面上看似有 2n 种情况,但其实对于每个点的搜索,它最多就把 n 个点访问一遍,也就是 n 次,所以对 n 个点全部搜索一遍总共不会超过 n2 次。
【注意】
搜索结束的控制:只有把所有的点不重复的遍历一次后,才算成功:保证遍历不重复的同时,在搜索中增加一维来记录已经遍历过的个数;
边的存在不是明显的,需要检查下一次要搜索的数是否存在,用二分检索以降低复杂度。
#include
#include
using std::vector;
#define N_max 105
typedef unsigned long long ll;
int g[N_max][N_max];
ll ipt[N_max];
int n;
vector<int>vis;
#define debug no_bug_at_all
ll ans[N_max];
int dfs(ll cur,int tot) {
if (tot > n)return 1;
//二分检查cur是否存在
int l = -1, r = n,m;
while (l+1 < r) {
m = (l + r) / 2;
if (ipt[m] <= cur)l = m;
else r = m;
}
//不存在
if (l == -1)return 0;
if(ipt[l] != cur)return 0;
//已经访问过
if (vis[l] == 1)return 0;
//标记访问位置
vis[l] = 1;
if (cur % 3 == 0)
if (1 == dfs(cur / 3, tot+1))
{
ans[tot] = cur;
return 1;
}
if (1 == dfs(cur * 2, tot+1)) {
ans[tot] = cur;
return 1;
}
else {
vis[l] = 0;
return 0;
}
}
int main() {
scanf("%d", &n);
for (int i = 0; i < n; ++i)
scanf("%llu", &ipt[i]);
//排序以二分查找
sort(ipt, ipt + n);
for (int i = 0; i < n; ++i) {
vis.resize(n);
if (1 == dfs(ipt[i], 1))
{
for (int i = 1; i <= n; ++i) {
printf("%llu%c", ans[i], i == n? '\n' : ' ');
}
return 0;
}
}
}
其实题目中的数字一定是非重复的,使用vis数组不仅没有意义,而且另一方面,假如有重复的,vis数组将会带来错误。考虑对重复数字的改进,可以对输入进行预处理,把重复的数字的个数记录到cnt数组,同时保证剩下的数没有重复;另一方面,搜索时要判断是否还有可用的数可以用(cnt[x]>0),每遍历到这个数字,就让cnt[x]–。