给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤mp,则称这个数列是完美数列。
现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
输入格式:
输入第一行给出两个正整数 N 和 p,其中 N(≤105)是输入的正整数的个数,p(≤109)是给定的参数。第二行给出 N 个正整数,每个数不超过 109。
输出格式:
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
输入样例:
10 8
2 3 20 4 5 1 6 7 8 9
输出样例:
8
题解:
一开始理解错了题意,认为可以先排序,然后得到最大的数,然后计数在它前面有多少个数乘p大于等于它,虽然这样只会在一个测试点得到WA,但是这并不是我们想要的。正确的做法应该是对数组先进行排序(升序),以样例来说,排序完后,顺序为:1,2,3,4,5,6,7,8,9,20;那么选择v[0]为最小数,乘p,那么可以取的M的可以为1,2,3,4,5,6,7,8。一共有8个,假如进行第二次遍历,从v[1]开始,那么可以选择便有2,3,4,5,6,7,8,9,共有8个。我们只需要这样遍历便可以得到最长的完美数列。
方法:
双指针法:
| 第一次遍历 | i | j,j指到这里时退出,j还小于n,继续遍历,j-i=8; | ||||||||
| 第二次遍历 | i | j,j指到这里时退出,j=n,结束遍历,j-i=8; | ||||||||
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 20 |
while(j<n){
while(j<n&&v[j++]<=v[i]*p)
num = max(num,j-i);
i++;
}
完整代码 :
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,i,j=0,num=-1;
long long p;
cin>>n>>p;
long long v[100001];
for(i=0;i<n;i++)
scanf("%lld",&v[i]);
i=0;
sort(v,v+n);
while(j<n){
while(j<n&&v[j++]<=v[i]*p)
num = max(num,j-i);
i++;
}
cout<<num;
return 0;
}
该博客详细解析了PAT乙级考试中的一道题目——完美数列。博客介绍了如何判断一个数列是否为完美数列,并提供了一种解题思路,即对数列进行排序后,采用双指针法寻找最长的完美子序列。通过示例解释了错误的解题方法和正确的解题策略,最后给出了完整的代码实现。
2万+

被折叠的 条评论
为什么被折叠?



