题目大意
有一个单调不升的序列B,由B的数两两求gcd得出A。现在给出A,求B。
n<=1000,a[i]<=1e9
时间限制 1.5s
空间限制 256M
解题思路
首先A中最大的两个数一定是B中最大的两个数,而唯一比B[3]大的数只有可能是gcd(B[1],B[2]),所以在A中去掉gcd(B[1],B[2])(注意是2个)后,最大的数就是B[3]。
由此类推,B序列中每确定一个数,就把它与前面的数的gcd从A序列中去掉,然后后一个数就是A序列中剩余的最大的数了。
#include<cstdio>
#include<algorithm>
#define maxn 1006
#define fr(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const ll ding=10000007;
bool cmp(int a,int b)
{
return a>b;
}
int i,j,n,t,tot,h[ding+10][2],a[maxn*maxn],b[maxn*maxn];
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int hash(int x)
{
int t=(x-1)%ding+1;
while (h[t][0]!=0 && h[t][0]!=x)
t=t%ding+1;
h[t][0]=x;
return t;
}
int main()
{
scanf("%d",&n);
fr(i,1,n*n)
{
scanf("%d",&a[i]);
t=hash(a[i]);
h[t][1]++;
}
sort(a+1,a+n*n+1,cmp);
b[1]=a[1],b[2]=a[2],tot=2;
t=hash(a[1]),h[t][1]--;
t=hash(a[2]),h[t][1]--;
t=hash(gcd(a[1],a[2])),h[t][1]-=2;
fr(i,3,n*n)
{
t=hash(a[i]);
if (h[t][1]>0) h[t][1]--,b[++tot]=a[i];
if (tot==n) break;
fr(j,1,i-1)
{
t=hash(gcd(a[i],a[j]));
h[t][1]-=2;
}
}
fr(i,1,n) printf("%d ",b[i]);
printf("\n");
return 0;
}