题目分析
题目难度:普及/提高-
题目含义就是 从n个数中选k个,找出这很多组k个数的最大的最大公约数!
显然不能用搜索暴力去找,那样时间复杂度肯定不允许,那么根据lzn给出的思路,可以这么来做:
对于输入的每一个能力值,对其进行因数分解,用一个数组来存储每一个因数出现的次数,如果一个因子是某数
的平方根,则只记录一次,不重复记录。
然后寻找答案时,k从1到n进行遍历,因子从输入能力值的最大值开始遍历,记为amax,如果因子amax出现的次数
大于等于k,则输出amax,否则amax-1,判断下一个数,直到循环结束。且当k+1的时候,amax不会再重复,而是
接着上次的amax继续下去,因为已经不会有更大的因子出现次数比当前的正在搜索的k大了!
AC代码
//Author:snnu_lgw
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;//输入数的个数
int a[10000+100]; //输入的能力值
int num[1000000+100];//记录每一个因数出现的次数,如果没有出现,次数为0。因数的范围为 1~1e6
int main()
{
int amax=-1; //记录能力值的最大值
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
amax=max(amax,a[i]);
for(int j=1;j<=sqrt(a[i]);j++)
{
if(a[i]%j==0)
{
int b = a[i]/j; //这里不用考虑精度问题,一定整除不用精确到1e-6之类的
if(j!=b) //平方根只出现一次
num[b]++;
num[j]++;
}
}
}
for(int i=1;i<=n;i++)
{ //寻找i个人最大的最大公约数,那肯定要从最大的因子开始判断即inf
for(int j=amax;j>=1;--j)
{
if(num[j]>=i)
{
printf("%d\n",j);
amax=j; //更新目前的最大值,因子出现i次的最大的因数是amax(j),避免重复判断
break;
}
}
}
return 0;
}