版权声明:有善始者实繁,能克终者盖寡。 https://blog.csdn.net/weixin_43987810/article/details/86765990
题目:
1030 完美数列 (25 分)
给定一个正整数数列,和正整数 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
分析:
先使用排序,使得数组内元素为从小到大。
另外注意一点就是找到一对max和min,其间所有的元素都包含在长度以内,即完美数列的每个元素都在【min, max】以内。
最后注意比较的时候牵扯乘法,不声明long long的话会导致溢出(不要只看到题目给定的范围在int范围内,程序中还可能对其做乘法等运算)。
做法1:长度递减遍历每个拥有此长度的数组,看其是否完美。比如说:开始的时候len = N, 因此只需判断最大的数组即可;之后len = N - 1, 此时看a2-aN这个数组和 a1-a(N - 1)这个数组,以此类推。(超时)
做法2:min从最小值开始遍历,每次固定min,看数组最大长度;如果后一个数组的长度比该数组的长,len = 后一个数组长度。
代码:
做法一代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
long long v[100010];
int N, p;
int i, j;
int k, l;
int last;
cin >> N >> p;
for(i = 0; i < N; i++)
scanf("%lld", &v[i]);
sort(v, v + N);
for(last = N - 1; last >= 0; last--)
for(i = 0, j = last; j <= N - 1; i++, j++)//两重循环导致超时
if(v[j] <= v[i] * p)
{
cout << last + 1 << endl;
return 0;
}
return 0;
}
做法二代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
long long v[100010];
int main()
{
int N, p;
int i, j;
int len = 0;
cin >> N >> p;
for(i = 0; i < N; i++)
scanf("%lld", &v[i]);
sort(v, v + N);
for(i = 0; i < N; i++)
{
if(i + len < N && v[i + len] <= v[i] * p)//此处判断避免超时
{
for(j = i + len + 1; j <= N - 1; j++)
if(v[j] > v[i] * p)
break;
len = j - i;
}
}
cout << len << endl;
return 0;
}