给定一个正整数数列,和正整数 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
思路
1、可以利用qsort函数排序,则很好确定框定范围内的最大最小值M和m;
2、排序后可以框定一个范围l,可以想象为长度为l的框在数组上滑动,最大最小值就在两端。然后l从小到大变化,对于每一个l在数组上滑动的时候,只要满足一次 M≤mp即可证明当前l满足要求,l可继续增大,直到滑动完数组后都不满足,即可输出l-1;
备注:l只能从小到大递增,不能从大到下递减,不然测试点4超时过不了,若l从大到小递减,对于每一个还没找到的l,都要滑动完全部数组才可以,若l从小到大递增,对于每一个还没找到的l,只需要对比一次即可,复杂度会小很多。
3、p在int型范围内,但是需要计算m*p,则可能超过int型范围,把数组改成long型后通过;
AC代码
#include<stdio.h>
#include<stdlib.h>
int compare(const void* a,const void* b){//compare函数,辅助qsort排序
return *(long long*)b-*(long long*)a;
}
int main(){
int n,p,l=1;
scanf("%d %d",&n,&p);
long num[n];//long型,因为m*p可能会超int
for(int i=0;i<n;i++)scanf("%ld",&num[i]);//接收数据
qsort(num,n,sizeof(long),compare);//从大到小排序,方便计算最大最小值
while(l<=n){
int i=0;
for(i=0;i<n-l+1;i++)if(num[i]<=num[i+l-1]*p)break;//l只需满足一次
if(i==n-l+1)break;//若l一次都不满足会=n-l+1,while循环跳出
l++;
}
printf("%d",l-1);//因为跳出while循环时l不满足,所以最大满足的为l-1
return 0;
}