【JZOJ4699】Password

Description

这里写图片描述

Solution

补坑
因为A序列是个矩阵,所以B序列肯定在A序列里。

首先,B序列中最大的数肯定是A序列最大的,B序列次大的也是A序列中次大的,那么这样想,除了最大和次大的最大公约数外,第三大就是A序列中第三大的。

于是,每次把新加入的答案与之前的两两gcd,去掉的得出的结果(去掉两个)即可。

Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 1001
#define mo 3000007
using namespace std;
int a[N*N];
int c[N];
int h[mo],z[mo];
bool cmp(int x,int y)
{
    return x>y;
}
bool find(int x)
{
    int p=x%mo;
    while(z[p] && z[p]!=x) p=(p+1)%mo;
    return h[p];
}
void hash(int x)
{
    int p=x%mo;
    while(z[p] && z[p]!=x) p=(p+1)%mo;
    z[p]=x;
    h[p]++;
}
void del(int x,int t)
{
    int p=x%mo;
    while(z[p] && z[p]!=x) p=(p+1)%mo;
    if(z[p]==x)
    {
        if(t==-1) h[p]=0;
        else h[p]-=t;
        h[p]=max(h[p],0);
    }
}
int gcd(int x,int y)
{
    int z;
    while(x%y!=0)
    {
        z=x%y;
        x=y;
        y=z;
    }
    return y;
}
int main()
{
    int n;
    cin>>n;
    fo(i,1,n*n) scanf("%d",&a[i]),hash(a[i]);
    sort(a+1,a+n*n+1,cmp);
    fo(i,1,n*n)
    if(find(a[i]))
    {
        c[++c[0]]=a[i];
        del(c[c[0]],1);
        fo(j,1,c[0]-1)
        del(gcd(c[j],c[c[0]]),2);
        if(c[0]==n) break;
    }
    fo(i,1,c[0]) printf("%d ",c[i]);
}
posted @ 2016-08-15 14:52  sadstone  阅读(29)  评论(0编辑  收藏  举报