Codeforces Round #565 (Div. 3)--D. Recover it!--思维+欧拉筛

D. Recover it!

time limit per test

4 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Authors guessed an array aa consisting of nn integers; each integer is not less than 22 and not greater than 2⋅1052⋅105. You don't know the array aa, but you know the array bb which is formed from it with the following sequence of operations:

  1. Firstly, let the array bb be equal to the array aa;
  2. Secondly, for each ii from 11 to nn:
    • if aiai is a prime number, then one integer paipai is appended to array bb, where pp is an infinite sequence of prime numbers (2,3,5,…2,3,5,…);
    • otherwise (if aiai is not a prime number), the greatest divisor of aiai which is not equal to aiai is appended to bb;
  3. Then the obtained array of length 2n2n is shuffled and given to you in the input.

Here paipai means the aiai-th prime number. The first prime p1=2p1=2, the second one is p2=3p2=3, and so on.

Your task is to recover any suitable array aa that forms the given array bb. It is guaranteed that the answer exists (so the array bb is obtained from some suitable array aa). If there are multiple answers, you can print any.

Input

The first line of the input contains one integer nn (1≤n≤2⋅1051≤n≤2⋅105) — the number of elements in aa.

The second line of the input contains 2n2n integers b1,b2,…,b2nb1,b2,…,b2n (2≤bi≤27501312≤bi≤2750131), where bibi is the ii-th element of bb. 27501312750131 is the 199999199999-th prime number.

Output

In the only line of the output print nn integers a1,a2,…,ana1,a2,…,an (2≤ai≤2⋅1052≤ai≤2⋅105) in any order — the array aa from which the array bb can be obtained using the sequence of moves given in the problem statement. If there are multiple answers, you can print any.

Examples

input

Copy

3
3 5 2 3 2 4

output

Copy

3 4 2 

input

Copy

1
2750131 199999

output

Copy

199999 

input

Copy

1
3 6

output

Copy

6 

给出一个序列,然后b序列=a序列+a变化的序列。给出b序列(打乱顺序),求原先的a序列。

利用欧拉筛先筛除数的最大因子、确定是第几个素数。

然后把所有的数从小到大排序,从大到小枚举,然后对于每一个数来说。

若x是素数,那么确定它的位置pos,保存入答案。那么把pos加入队列,加入队列是为了防止把x和x变化的数都保存入答案。

若x是非素数,则x一定是a序列内的数,因为从大到小排序,它不可能是其他的因子。然后把它最大因子的加入队列。

#include <algorithm>    //STL通用算法
#include <bitset>     //STL位集容器
#include <cmath>
#include <cstdio>
#include <cstring>
#include <deque>      //STL双端队列容器
#include <exception>    //异常处理类
#include <fstream>
#include <functional>   //STL定义运算函数(代替运算符)
#include <limits>
#include <list>      //STL线性列表容器
#include <map>       //STL 映射容器
#include <iomanip>
#include <ios>      //基本输入/输出支持
#include<iosfwd>     //输入/输出系统使用的前置声明
#include <iostream>
#include <istream>     //基本输入流
#include <ostream>     //基本输出流
#include <queue>      //STL队列容器
#include <set>       //STL 集合容器
#include <sstream>    //基于字符串的流
#include <stack>      //STL堆栈容器    
#include <string>     //字符串类
#include <vector>     //STL动态数组容器
#define ll long long
using namespace std;
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
//priority_queue<int,vector<int>,less<int> >q;
int dx[]= {-1,1,0,0,-1,-1,1,1};
int dy[]= {0,0,-1,1,-1,1,1,-1};
const int maxn = 400000+66;
const int maxm=2750131+66;
const ll mod=1e9+7;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
const int INF=99999999;
int n,m;
int a[maxn];
int isp[maxm + 5],vis[maxm + 5];
int re[maxm + 5],p[maxm + 5];
int cnt;
void shai()
{
    for (int i = 2; i <= maxm; i++)
    {
        if (!vis[i])
        {
            p[++cnt] = i;
            re[i] = cnt;			/// 表示i对应第几个素数
            isp[i] = 1;
        }
        for (int j = 1; j <= cnt && i * p[j] <= maxm; j++)
        {
            vis[i * p[j]] = 1;
            re[i * p[j]] =i;		/// 筛选其最大因子 
            if (i % p[j] == 0)
                break;
        }
    }
}
int main()
{
    int n;
    shai();
    while(scanf("%d",&n)!=EOF)
    {
        rep(i,1,2*n)
        {
            scanf("%d",&a[i]);
        }
        sort(a+1,a+2*n+1);
        priority_queue<int>q;
        vector<int>ans;
        while(q.size())
            q.pop();
        ans.clear();
        dep(i,2*n,1)
        {
            int v=a[i];
            if(isp[v])
            {
                if(q.size()&&q.top()==v)
                {
                    q.pop();
                    continue;
                }
                ans.push_back(re[v]);
                q.push(re[v]);
            }else
            {
                if(q.size()&&q.top()==v)
                {
                    q.pop();
                    continue;
                }
                ans.push_back(v);
                q.push(re[v]);
            }

        }
        for(int i=0;i<ans.size();i++)
        {
            printf("%d%c",ans[i],i==ans.size()-1?'\n':' ');
        }
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值