题目
题目链接:https://atcoder.jp/contests/arc122/tasks/arc122_e
给定一个长度为 (n) 的正整数序列 (a),要求重排 (a) 中的元素,记 (b_i) 为重排后 ( ext{lcm}(a_1,a_2,cdots,a_i)),要求 (b_1<b_2<cdots<b_n)。
给出一个合法的重排方案。
(nleq 100;a_ileq 10^{18})。
思路
考虑最后一位的数字。假设填 (a_i),显然必须满足 ( ext{gcd}(a_i, ext{lcm}_{i
eq j}(a_j))
eq a_i)。
那么从后往前不断确定最后一位数字即可。因为如果一个数字可以填在第 (i) 位,那么显然也可以填在第 (j(j<i)) 位。
时间复杂度 (O(n^3log a))。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=110;
int n;
ll a[N],b[N],g[N][N];
bool used[N];
ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b)
{
return a/gcd(a,b)*b;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%lld",&a[i]);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
g[i][j]=gcd(a[i],a[j]);
for (int i=n;i>=1;i--)
{
bool flag=0;
for (int j=1;j<=n;j++)
if (!used[j])
{
ll l=1;
for (int k=1;k<=n;k++)
if (!used[k] && j!=k)
l=lcm(l,g[j][k]);
if (l<a[j])
{
b[i]=a[j]; used[j]=1;
flag=1; break;
}
}
if (!flag) return printf("No"),0;
}
printf("Yes
");
for (int i=1;i<=n;i++)
printf("%lld ",b[i]);
return 0;
}