原题链接: https://codeforces.com/contest/1407/problems
测试样例
input
7
2
2 5
4
1 8 2 3
3
3 8 9
5
64 25 75 100 50
1
42
6
96 128 88 80 52 7
5
2 4 8 16 17
output
5 2
8 2 1 3
9 3 8
100 50 25 75 64
42
128 96 80 88 52 7
17 2 4 8 16
Note
In the first test case of the example, there are only two possible permutations b — [2,5] and [5,2]: for the first one c=[2,1], for the second one c=[5,1].
In the third test case of the example, number 9 should be the first in b, and GCD(9,3)=3, GCD(9,8)=1, so the second number of b should be 3.
In the seventh test case of the example, first four numbers pairwise have a common divisor (a power of two), but none of them can be the first in the optimal permutation b.
题意: 说实话,这个题目我还是不太懂,暂且按我的理解来说吧(有错误请指正),给定一个数组,你可以对该数组进行任意排列,请你找出这样的数组
,使得产生的数组
是所有排列中产生字典序最大的。其中
。
解题思路: 我们要使得字典序最大,就要尽可能使得最大,而
,故不管怎样,
越大,
就越小,所以我们必须要让前面的
都尽可能大。 那么自然可以知道,把具有最大公约数的放前面。(
为1的时候自然是放数组中元素最大的),接下来我们就是要以前面的最大公约数为参考去得到接下来的最大公约数,故我们每轮都要保存最大公约数的值。为了之前确定了的不参加计算,所以我们要开一个used数组来判断元素是否已加入
数组。OK,我们具体看代码。
AC代码
/*
*
*/
//POJ不支持
//i为循环变量,a为初始值,n为界限值,递增
//i为循环变量, a为初始值,n为界限值,递减。
using namespace std;
const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 1e3+5;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为自定义代码模板***************************************//
int t,n;
int a[maxn];
bool used[maxn];
int GCD(int n,int m){
int temp;
while(n%m){
temp=n%m;
n=m;
m=temp;
}
return m;
}
int main(){
//freopen("in.txt", "r", stdin);//提交的时候要注释掉
IOS;
while(cin>>t){
while(t--){
cin>>n;
rep(i,0,n-1)
cin>>a[i];
memset(used,false,sizeof(used));
int pos,gcd=0;
//注意0和其他数的最大公约数为其本身。
rep(i,0,n-1){
pos=-1;
rep(j,0,n-1){
if(!used[j]){
if(pos==-1||GCD(gcd,a[j])>GCD(gcd,a[pos])){
//比较得到最大的ci。
pos=j;
}
}
}
//更新最大公约数,去计算接下来的数。
gcd=GCD(gcd,a[pos]);
cout<<a[pos]<<" ";
used[pos]=true;
}
cout<<endl;
}
}
return 0;
}