模拟赛 最大公约数(时间限制:1s,空间限制:128MB)

来源:互联网 发布:webpack node modules 编辑:程序博客网 时间:2024/05/09 14:40

问题描述

话说CD比较欠扁,他表示在课室的日子没有教主在旁边打他的日子太寂寞了,所以这一晚,他终于来到了电脑室被打。由于CD是大家的宠物,于是大家都来打CD了。电脑室里有n个人,第i个人希望打CD ai下。但是太多人打CD,他又会不爽,于是他规定只能有K个人打到他,并且为了公平起见,最终K个人打他的次数都必须是相同的,CD规定这个次数就是这K个人希望打他的次数的最大公约数。为什么是最大公约数呢?因为他觉得被打的次数是GCD的话他才会变成Glad CD。之前说了,CD比较欠扁,于是CD希望,K个人打他的次数的和最大。你能告诉他他最后总共会被打多少下么?

输入格式

第一行两个正整数n,k。
第二行n个正整数,表示每个人希望打CD多少下。

输出格式

输出一个正整数表示CD会被打多少下。

样例输入输出

gcd.in 
3 1

1 2 3

gcd.out

3

数据说明

对于30%的数据,保证k≤n≤20。
对于50%的数据,保证输入中所有数小于5000。

对于100%的数据,保证输入中所有数小于500000,k≤n。

题解

一道怪怪的题。

暴力可以枚举答案,看看每个可能的答案能整除多少个数。O(n√n),80分。

#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<cmath>#include<algorithm>using namespace std;int n,m,a[500002],maxs,ct[500002];void init(){scanf("%d%d",&n,&m);int i;for(i=1;i<=n;i++) {scanf("%d",&a[i]); maxs=max(maxs,a[i]);}}int gcd(int x,int y){if(y==0) return x;else return gcd(y,x%y);}void work(){if(m==1) {printf("%d\n",maxs); return ;}else if(m==n)   {int i,ans=a[1];    for(i=2;i<=n;i++) ans=gcd(ans,a[i]);    printf("%d\n",ans);   }int i,j;for(i=1;i<=n;i++)   {for(j=1;j<=sqrt(a[i]);j++)       {if(a[i]%j==0) {ct[j]++; ct[a[i]/j]++;}}   }for(i=maxs;i>=1;i--)   {if(ct[i]>=m) {printf("%d\n",i*m); return ;}}}int main(){freopen("gcd.in","r",stdin);freopen("gcd.out","w",stdout);init(); work(); return 0;}

正解要用到“调和级数求和”,先开50W个桶存下每个数出现了几次,然后枚举最后的答案gcd,然后再暴力枚举所有它的倍数,看出现次数是否大于等于k就可以了。这样做的复杂度最坏是O(n+n/2+n/3+…+n/n)=O(nlnn)。

#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<cmath>#include<algorithm>#define ll long longusing namespace std;int n,m,a[500002],maxs,ct[500002];int f[500002];void init(){scanf("%d%d",&n,&m);int i;for(i=1;i<=n;i++)   {scanf("%d",&a[i]);    ct[a[i]]++; maxs=max(maxs,a[i]);   }}void work(){int i,j;for(i=1;i<=maxs;i++)for(j=1;j*i<=maxs;j++)   f[i]+=ct[j*i];for(i=maxs;i>=1;i--)   {if(f[i]>=m)       {printf("%I64d",(ll)i*m); return;}   }}int main(){freopen("gcd.in","r",stdin);freopen("gcd.out","w",stdout);init(); work(); return 0;}

0 0
原创粉丝点击