题目描述
输入n个正整数,从中任取出k个数,使这k个数的最大公约数最大。
输入
第一行两个整数,即n和k(k≤n≤50000),随后一行有n个整数(均不大于100000)。
输出
输出一个整数,即k个数的最大公约数最大的一个。
样例输入 Copy
4 3 123 369 999 36
样例输出 Copy
9
解题思路:要求多位数字的最大公约数,需要找到他们共同的特点,公约数是能被整除的,而多个数的公约数说明能被这些书整除,所以我们只需要找到能被他们能共同整除的数且最大就行了。
答案:
#include <iostream>
#include <set>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<sstream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
using
namespace
std;
int
a[100001],b[100001];
int
main()
{
int
n,t,i,j;
scanf
(
"%d %d"
,&n,&t);/*scanf比cin快,对于有许多测试数据的,尽量用scanf*/
for
(
int
i=0;i<n;i++)
scanf
(
"%d"
,&a[i]);
int
g=0;/*g是公约数中最大的那个数*/
for
(
int
i=0;i<n;i++)
for
(
int
j=1;j<=
sqrt
(a[i]);j++)/*尽量缩短循环的次数,不然容易超时*/
if
(a[i]%j==0)
{
b[j]++;
if
(j != a[i] / j) b[a[i]/j]++;/*这里一定要有j!=a[i]/j,不然会有数的次数被反复增加。比如a[i]=64时,sqrt(64)=8,b[8]就会多增加一次*/
if
(g<j)g=j;
if
(g<a[i]/j)g=a[i]/j;
}
for
(j=g;j>=2;j--)
{
if
(b[j]==0)
continue
;/*减少时间*/
if
(b[j]>=t)
/*b[j]存放的是能被整除的数,出现的次数,b[j]>=t然不是b[j]==t是因为可能会有一个能被整除的数多次出现,而又没有其他数出现的次数是t,所以只能b[j]>=t。
举个例子:
4 2
2 2 2 2
如果b[j]==t,结果是1(答案错误)
如果b[j]>=t,结果是2(答案正确)
*/
break
;
}
printf
(
"%d"
,j);
}