题意:
给出乱序的GCD table的n2个元素,恢复原来的序列
分析:
我们让答案a1≤ a2 ≤ ... ≤ an.很显然gcd(ai, aj) ≤ min(ai,a)=amin(i, j).
由于gcd(an, an) = an ≥ ai ≥ gcd(ai, aj),(i,j)∈1 ≤ i, j ≤ n.也就是说an是最大的那个数,我们得到an并把它从表里删掉.
现在表里的gcd(ai, aj),(i,j)∈1 ≤ i, j ≤ n,都有1 ≤ min(i, j) ≤ n − 1.
接下来从上面那个式子,gcd(ai, aj) ≤ amin(i, j) ≤ an − 1 = gcd(an − 1, an − 1).表里有gcd(an − 1, an − 1),那么现在最大的元素就是an − 1.
由于我们已经知道了an−1和an,我们就把gcd(an − 1, an − 1),gcd(an − 1, an ),gcd(an , an − 1)从表里删去.
现在表里的gcd(ai, aj),(i,j)∈1 ≤ i, j ≤ n,都有1 ≤ min(i, j) ≤ n − 2.
重复以上过程从k∈{n−2→1},让ak是表中的最大元素,删除表中gcd(ak, ak),gcd(ai, ak),gcd(ak, ai),i∈(k,n].
表用multiset或者map来维护,我们就可以在O(n2logn)时间解决问题了
代码:
map:
//
// Created by TaoSama on 2015-10-04
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 3e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, ans[505];
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(scanf("%d", &n) == 1) {
map<int, int> mp;
for(int i = 0; i < n * n; ++i) {
int x; scanf("%d", &x);
++mp[x];
}
for(int i = 1; i <= n; ++i) {
ans[i] = mp.rbegin()->first;
for(int j = 1; j <= i; ++j) {
int x = __gcd(ans[i], ans[j]);
mp[x] -= 2;
if(mp[x] <= 0) mp.erase(x);
}
}
for(int i = 1; i <= n; ++i)
printf("%d%c", ans[i], " \n"[i == n]);
}
return 0;
}
multiset:
//
// Created by TaoSama on 2015-10-04
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 3e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, ans[505];
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(scanf("%d", &n) == 1) {
multiset<int> s;
for(int i = 0; i < n * n; ++i) {
int x; scanf("%d", &x);
s.insert(x);
}
for(int i = 1; i <= n; ++i) {
ans[i] = *s.rbegin();
s.erase(--s.end());
for(int j = 1; j < i; ++j) {
int x = __gcd(ans[i], ans[j]);
s.erase(s.find(x));
s.erase(s.find(x));
}
}
for(int i = 1; i <= n; ++i)
printf("%d%c", ans[i], " \n"[i == n]);
}
return 0;
}