Codeforces Tutorial
A. GCD Table
Problem Analysis
对于(G_{n imes n})中的每个元素({g_i}_j)有:
[{g_i}_j=gcd(a_i,a_j)
]
要求构造数组(a_{1 imes n})
假设已经构造出 (a_1,a_2,cdots,a_n),顺序不影响结果,不妨设(a_i le a_j),如果(i lt j)
(gcd(a_n, a_n) = a_n ≥ a_i ≥ gcd(a_i, a_j))for every (1 ≤ i, j ≤ n.)
所以可以
- 每一次取出最大的元素(a_k)
- 然后删除 对于(k lt i le n),删除(gcd(a_k,a_k),gcd(a_i,a_k),gcd(a_k,a_i))
Acepted Code
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cmath>
#include<map>
#include<istream>
#include<cassert>
#include<set>
#include<functional>
#define DEBUG(x) cout<<#x<<" = "<<x<<endl
#define DEBUG2(x,y) cout<<#x<<" = "<<x<<" , "
<<#y<<" = "<<y<<endl
using namespace std;
typedef long long ll;
int _gcd(int a,int b)
{
if(b==0)return a;
return _gcd(b,a%b);
}
int gcd(int a,int b)
{
if(a<b)swap(a,b);
return _gcd(a,b);
}
map<int,int>cnt;
multiset<int,greater<int> >tbl;
int main()
{
// freopen("in.txt","r",stdin);
int n;
scanf("%d",&n);
for(int ii=0;ii<n*n ;ii++ ){
int t;
scanf("%d",&t);
cnt[t]++;
tbl.insert(t);
}
vector<int>ans;
for(auto ii:tbl){
if(cnt[ii]==0)continue;
for(int jj=0;jj<ans.size();jj++){
cnt[gcd(ans[jj],ii)]-=2;
}
cnt[ii]--;
ans.push_back(ii);
}
for(auto a:ans){
printf("%d ",a);
}
}
Wrong Answer Cases
Test 1
What I Learn
构造最后结果的状态,根据最终状态推导出求解的过程