最大公约数

https://zybuluo.com/ysner/note/1175822

题面

现有\(n\)个数,询问选出\(k\)个数的\(gcd\)的最大值。

  • \(30pts\) \(n\leq20\)
  • \(60pts\) 保证输入中所有数小于\(5000\)
  • \(100pts\) 保证输入中所有数小于\(500000\)
  • \(k\leq n\)

    解析

    \(n\leq20\)

    \(O(2^n)\)枚举。

    \(n\leq5000\)

    枚举\(gcd\)最大值,看是否有\(k\)个数能将其除尽。

    \(n\leq5*10^5\)

    话说我想了半天为什么不给出\(n\)的范围,竟然没想到是因要开桶,\(n\)的范围无意义。。。
    于是我们开个桶\(a[i]\)记录每个数出现多少次。
    然后枚举\(gcd\)最大值。
    要判断有多少个数能将其除尽,直接枚举\(t\)\(\sum a[gcd*t](t\in N^*)\)即可。
    复杂度最坏为\[O(n+\frac{n}{2}+\frac{n}{3}+...+1)\]
    等价于\(O(nlogn)\)
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define ll long long
#define re register
#define il inline
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int N=5e5+100;
int n,k,a[N],ans=1,mx;
int main()
{
  freopen("gcd.in","r",stdin);
  freopen("gcd.out","w",stdout);
  n=gi();k=gi();
  fp(i,1,n)
    {
      re int x=gi();mx=max(mx,x);
      a[x]++;
    }
  fq(i,mx,1)
    {
      re int sum=0;
      for(re int j=1;j*i<=mx;j++) sum+=a[j*i];
      if(sum>=k) {printf("%lld\n",1ll*k*i);return 0;}
    }
  fclose(stdin);
  fclose(stdout);
  return 0;
}

转载于:https://www.cnblogs.com/yanshannan/p/9155453.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值