JZOJ 4699 Password

題目大意

有一個單調不升的序列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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章