最大公约数一定是n个数中至少两个数的因子,因此,只要将所有数的因子做出统计,并求出出现次数大于等于2次的最大的因子即可。利用map可以很简单的解决。
AC代码:
#include<bits/stdc++.h>
#include<map>
using namespace std;
int main(void){
int n,a,temp = 1;
cin>>n;
map<int ,int> m;
m.clear();
while(n--){
cin>>a;
for(int i=1;i*i<=a;i++){
if(a%i==0){
m[i]++;
// printf("%d:%d\n",i,m[i]);
if(m[i] >= 2)
temp = max(temp,i);
if(i != a/i){
m[a/i]++;
// printf("%d:%d\n",a/i,m[a/i]);
if(m[a/i] >= 2)
temp = max(temp,a/i);
}
}
}
}
cout<<temp<<endl;
return 0;
}
还有一种做法,因为题目中给出了每个数都小于1e6,所以可以用一个数组将每个数字出现的次数储存起来。从最大的那个数开始向下判断,验证是不是该数列的公约数,如果是,就一定数最大的(向下)。
这个比上面的那个快很多。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
int arr[maxn];
int main(void){
int n,t,mmax = 0,sum,i,j;
cin>>n;
memset(arr,0,sizeof(arr));
for(int i=1;i<=n;i++){
cin>>t;
arr[t]++;
mmax = max(mmax,t);
}
for(i=mmax;i>=1;i--){
sum = 0;
for(j = i;j<=mmax;j+=i){ //包含因子j的数字总个数至少为二
sum += arr[j];
if(sum >= 2) break;
}
if(sum >= 2) break;
}
cout<<i<<endl;
return 0;
}