给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤mp,则称这个数列是完美数列。
现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
输入格式:
输入第一行给出两个正整数 N 和 p,其中 N(≤10^5)是输入的正整数的个数,p(≤ 10^9)是给定的参数。第二行给出 N 个正整数,每个数不超过 10^9。
输出格式:
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
输入样例:
10 8
2 3 20 4 5 1 6 7 8 9
输出样例:
8
题目链接:https://pintia.cn/problem-sets/994805260223102976/problems/994805291311284224
思路:这道题目设计的非常好,对程序的算法有一定的要求,算法思想有点类似于KMP最长字符串匹配算法。
(1)当然是由小到大排序数列;
(2)遍历数组,对于每给定的一个元素,从当前元素i开始查找满足条件的最大元素个数,不断更新最大元素个数,下次匹配当前元素j直接跨到i+max处,从而降低了程序算法时间复杂度。值得学习
下面是AC代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
typedef long long ll;
ll a[maxn];
int main()
{
int n,p;
while(scanf("%d%d",&n,&p)==2)
{
memset(a,0,sizeof(a));
int max,k;
for(int i=0;i<n;++i)
{
scanf("%ld",&a[i]);
}
sort(a,a+n); //排序
for(int i=0;i<n;++i)
{
if(i+max>=n) //及时退出
break;
for(int j=i+max;j<n;++j)
{//j=i+max是算法精髓
if(a[j]<=a[i]*p)
{
k = j-i+1; //下标+1
if(k>max)
{//更新最大值
max = k;
}
}
else //退出内循环
{
break;
}
}
}
printf("%d\n",max);
}
return 0;
}