完美数列
题目描述
给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M ≤ mp,则称这个数列是完美数列。
现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
输入格式
输入第一行给出两个正整数 N 和 p,其中 N(≤$10^5$)是输入的正整数的个数,p(≤$10^9$)是给定的参数。第二行给出 N 个正整数,每个数不超过 $10^9$。
输出格式
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
输入样例
1 | 10 8 |
输出样例
1 | 8 |
问题解决
解题思想
方法一:递归方法,测试点4会超时
注意参数p和数组a[]要定义成long或long long型,否则会导致测试点5不通过,想一下为什么?输入后先对数组a[]进行升序排序,然后递归调用函数Max_Per_Array():
- 终止条件:a[j] <= p x a[i],满足则直接返回j-i+1;
- 递归条件:a[j] > p x a[i],先后判断最大值前移一位满足而最小值后移一位不满足和最大值前移一位不满足而最小值后移一位满足这两个条件是否满足,若满足,则只需进行相应的单个调用即可,若都不满足,则依次进行两个调用,返回最大的即可。
此法思路很简单,但是,运行效率不高,提交时测试点4会超时,因此有下面更高效的方法。
方法二:优化双层循环方法
先初始化完美数列最多元素个数,至少为1个;用双层循环,i从0开始依次递加作外层循环,a[i]为最小值,对于每一个i,j从i+max_coun开始,a[j]为最大值,判断是否满足完美数列的条件,若满足,则更新max_coun为当前完美数列的元素个数,即j-i+1,然后继续累加j继续判断直到跳出内层循环;若不满足,则直接跳出内存循环,因为若当前的j不满足,则后面的最大值更大,必不满足。
此法效率较高,不会出现超时。
代码示例(C/C++)
代码1
1 | //递归方法,测试点4会超时 |
代码2
1 | //优化双层循环方法,全部通过测试点 |
题目来源:PAT乙级1030
作者:CHEN, Yue
单位:浙江大学