已知一个序列,两两gcd得到一张表 (图为
4,3,6,2
)
现在给出表中所有项(不按顺序),给出原序列一个合法解
预处理,把gcd表存为i的倍数在表中出现
hi
次,显然
hi
是完全平方数,取根号得到序列中i的倍数出现几次
贪心取最大的那个,把它从gcd表中删去,再取..
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
#include<map>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (250000+10)
typedef long long ll;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int n,a[MAXN];
map<int,int> h;
map<int,int>::iterator it;
int ans[MAXN]={0},siz=0;
void ad(int x)
{
it=h.find(x);
if (it!=h.end()) it->second++;
else h[x]=1;
}
int main()
{
freopen("data.in","r",stdin);
// freopen(".out","w",stdout);
cin>>n;
For(i,n*n) scanf("%d",&a[i]);
bool flag=0;
For(i,n*n-1)
{
if (a[i]!=a[i+1]) {
flag=1;break;
}
}
if (!flag)
{
For(i,n-1) printf("%d ",a[i]);printf("%d\n",a[n]);
return 0;
}
sort(a+1,a+1+n*n);
h.clear();
For(i,n*n)
{
for(int x=1;x*x<=a[i];++x)
{
if (a[i]%x==0)
{
ad(x);
if (x*x<a[i]) ad(a[i]/x);
}
}
}
for(it=h.begin();it!=h.end();it++) {
int p=it->first,s=it->second;
h[p]=sqrt(h[p]);
}
it=h.end();it--;
while(1)
{
int p=it->first,s=it->second;
// cout<<p<<' '<<s<<endl;
ans[++siz]=p;
if (siz==n) break;
for(int x=1;x*x<=p;++x)
{
if (p%x==0)
{
h[x]--;
if (x*x<p) h[p/x]--;
}
}
while (it->second==0) it--;
}
For(i,siz-1) printf("%d ",ans[i]); printf("%d\n",ans[siz]);
return 0;
}