链接
https://codeforces.com/contest/1176/problem/D
题解
从图的角度去考虑
我把输入数据中存在的数字都看作结点,每个数字有一条边指向它对应的数字,每个点的点权等于这种数字的出现次数
那么这时入读等于
1
1
1的点就肯定要作为序列
a
a
a的元素,这个时候将它们从图中删掉,然后把边也删掉,更新其所指向点的入读,依次进行下去即可
代码
#include<bits/stdc++.h>
#define maxn 3000000
#define linf (1ll<<60)
#define iinf 0x3f3f3f3f
#define eps 1e-8
#define cl(x) memset(x,0,sizeof(x))
#define mod 998244353ll
using namespace std;
typedef long long ll;
ll read(ll x=0)
{
int c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return f*x;
}
struct primes
{
ll prime[maxn], mark[maxn];
void init()
{
ll i, j;
for(i=2;i<maxn;i++)
{
if(!mark[i]){prime[++*prime]=i;}
for(j=1;j<=*prime and i*prime[j]<maxn;j++)
{
mark[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
}
}P;
ll N, b[maxn], indeg[maxn], to[maxn], cnt[maxn];
int main()
{
ll i;
P.init();
N=read();
for(i=1;i<=2*N;i++)b[i]=read(), cnt[b[i]]++;
for(i=2;i<=200000;i++)
{
if(!P.mark[i])to[i]=P.prime[i];
}
for(i=2;i<=200000;i++)
{
if(P.mark[i])
{
auto t=2;
while(i%t)t++;
to[i]=i/t;
}
}
for(i=2;i<=200000;i++)
{
if(cnt[i] and cnt[to[i]])indeg[to[i]]++;
}
queue<ll> q;
for(i=2;i<=200000;i++)
if(indeg[i]==0 and cnt[i])q.emplace(i);
while(!q.empty())
{
auto x=q.front(); q.pop();
for(auto i=1;i<=cnt[x];i++)printf("%lld ",x);
indeg[to[x]]--;
cnt[to[x]]-=cnt[x];
if(indeg[to[x]]==0)q.emplace(to[x]);
}
return 0;
}