原题:https://pintia.cn/problem-sets/994805260223102976/problems/994805291311284224
给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤mp,则称这个数列是完美数列。
现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
输入格式:
输入第一行给出两个正整数 N 和 p,其中 N(≤
)是输入的正整数的个数,p(≤
)是给定的参数。第二行给出 N 个正整数,每个数不超过
。
输出格式:
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
输入样例:
10 8
2 3 20 4 5 1 6 7 8 9
输出样例:
8
**想法一:**测试点四超时
将输入的数列进行从小到大排序,然后设当前最长长度maxlen=0。从
,
进行遍历,如何符合不等方式条件,则更新maxlen。(因为要找最大的maxlen所以left每次从最可能的位置开始)。
#include <iostream>
#include <algorithm>
using namespace std;
int cmp(int a1, int a2) {
return a1 < a2; // 升序排列
}
int main() {
int N, p;
cin >> N >> p;
int* num = new int[N];
for (int i = 0; i < N; i++) cin >> num[i];
sort(num, num + N, cmp);
int left = 0;
int right = N - 1;
int maxlen = 0; // 当前遍历的最大数列长度
for (; right >= maxlen; right--) {
for (left = right - maxlen; left >= 0; left--) {
if ((long)num[left] * p >= num[right]) {
if (right + 1 - left > maxlen) {
maxlen = right + 1 - left;
}
}
else break; // 再减少left已经不合理了
}
}
cout << maxlen << endl;
delete[] num;
system("pause");
}
问题记录:
1.测试点五出错,原因两个
的数乘起来可能超出了
的表述范围,所以至少申明一个
型的数字;
2.测试点四超时,即需要及时终止遍历的情况要及时break。
风格二:
也可以从左到右遍历
#include <iostream>
#include <algorithm>
using namespace std;
int cmp(int a1, int a2) {
return a1 < a2; // 升序排列
}
int main() {
int N;
long p;
cin >> N >> p;
int* num = new int[N];
for (int i = 0; i < N; i++) cin >> num[i];
sort(num, num + N);
int left;
int right;
int maxlen = 0; // 当前遍历的最大数列长度
for (left = 0; left < N - maxlen; left++) {
for (right = left + maxlen; right < N; right++) {
if (num[left] * p >= num[right]) {
if (right + 1 - left > maxlen) maxlen = right + 1 - left;
}
else break;
}
}
cout << maxlen << endl;
delete[] num;
system("pause");
}