題目大意
有一個單調不升的序列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;
}