原题链接
泰泰学长喜欢玩数字(不知道什么奇怪的癖好)。他在黑板上写下一个数字 x ,然后进行 n-1 次以下两种操作:
x 除以3 (必须能整除才能进行,即 x mod 3=0)
x 乘以2
每次操作完成后,泰泰学长在黑板上写上这个操作后的新数字,并让这个新数字作为新的 x 继续下一次操作。最后黑板上有 n 个数字。
由于泰泰学长是随机在黑板上的位置写数字的,所以他最后忘记了顺序。现在泰泰学长只知道所有的数字,你能帮助泰泰学长找出一种可能的序列吗?
保证答案一定存在。
Input
第一行是数字总数 n (2 ≤ n ≤ 100)。第二行包含 n 个数字a1,a2,…,an (1 ≤ ai ≤3×10^18),注意是不按顺序的。
Output
输出 n 个数字,按照泰泰学长写数字的顺序排列。
保证答案一定存在。
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
第一个样例中的可能顺序为:[9, 3, 6, 12, 4, 8]。此时开始的 x=9
题目描述
将给出的一串数字经过题目描述的操作之后,得到新的顺序,并输出
思路:很明显是dfs,由于不知道第一个开头数字是多少,所以需要试探每个数字作为开头,如果搜索完成,那么这个序列就符合条件,代码里面使用了map代替我们通常记录数字是否出现的book,这也是一个巧妙的地方,能够优化算法,应为你需要在这些数字中去寻找符合条件的是够存在,map就可以直接找到
代码如下
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
typedef long long ll;
ll a[105],vis[105];
map<ll, int> m;
int flag,n;
void dfs(ll num, int step)
{
if(step >= n-1)
{
flag = 1;
for(int i = 0;i < n;i++)
printf("%lld ",vis[i]);
printf("\n");
return;
}
//如果该数字符合操作1的条件,并且数组中还有剩余
if(num%3 == 0 && m.count(num/3))
{
m[num/3]--;
vis[step+1] = num/3;
dfs(num/3, step+1);
m[num/3]++;
}
//数组中还有剩余
if(m.count(num*2))
{
m[num*2]--;
vis[step+1] = num*2;
dfs(num*2, step+1);
m[num*2]++;
}
}
int main()
{
int i;
scanf("%d",&n);
for(i = 0;i < n;i++)
{
scanf("%lld",&a[i]);
if(m.count(a[i]))
m[a[i]]++;
else
m[a[i]] = 0;
}
//从数组的每个数字进行试探
for(i = 0;i < n;i++)
{
vis[0] = a[i];
dfs(a[i],0);
if(flag)
break;
}
return 0;
}