【NOIP模拟题】最大公约数
2016-01-28 13:05
351 查看
题意
给定NN个正整数a1,a2,...,ana_1,a_2,...,a_n,在其中选KK个数am1,am2,...,amka_{m_1},a_{m_2},...,a_{m_k},求k×max(gcd(ami))k\times max(gcd(a_{m_i}))。数据范围:所有输入中的数小于500000500000,k≤nk\leq n。
分析
kk是固定的,只用求max(gcd(ami))max(gcd(a_{m_i}))即可,即选择kk个数,使得这kk个数的最大公约数最大。首先的想法是正向求解,枚举kk个数,求最大公约数,取最大。
还可以调换顺序,剪枝优化。
好像还是会TLE。
那就考虑参数搜索,转化为判定性问题。
枚举每一个数,求满足这个数是因数的数的个数。
如果个数大于kk,则可以选取这个数。
时间复杂度为O(n1+n2+...+nn)=O(nlogn)O({n\over 1}+{n\over 2}+...+{n\over n})=O(n\log n)。
代码
#include <cstdio> #include <cctype> typedef long long Lint; const int M=500001; int n,k; int vis[M]; inline int read(void) { int x=0; char c=getchar(); for (;!isdigit(c);c=getchar()); for (;isdigit(c);c=getchar()) x=x*10+c-'0'; return x; } int calc(int w) { int cnt=0; for (int j=0;w*j<M;j++) cnt+=vis[w*j]; return cnt; } int main(void) { n=read(),k=read(); for (int i=1;i<=n;i++) vis[read()]++; for (int i=M-1;i>=1;i--) if (calc(i)>=k) {printf("%lld\n",(Lint)i*k);return 0;} return 0; }
相关文章推荐
- React-Native ListView加载图片淡入淡出效果的组件
- Linux下php安装Redis扩展
- Shell grep 和正则
- while循环
- PHP写入txt文件
- Flex中怎么给表格中的滚动栏定位
- HTML中怎么设置图片的位置和大小
- Unity3D项目工程性能优化
- Codeforces Round #339 (Div. 2) D. Skills
- 利用FFmpeg生成视频缩略图 2.3.1
- Undefined symbols for architecture armv7错误解决方法
- Matlab判断正态分布性检验
- Android开发学习之路--Android Studio项目目录结构简介
- 安装Android adb驱动
- Android 中如何计算 App 的启动时间?
- Android开发学习之路--Android Studio项目目录结构简介
- jenkins使用git SCM时changelog乱码(Jenkins部署在Linux上,任务在Windows Slave上构建)
- 弹出软键盘输入的时候完成后要关闭软件盘
- Spring4MVC中配置返回json格式数据
- 京东价格监控软件开源地址