題目
/*
1030. 完美數列(25)
給定一個正整數數列,和正整數p,設這個數列中的最大值是M,最小值是m,如果M <= m * p,則稱這個數列是完美數列。
現在給定參數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
*/
思路
// 考慮過程
// m[i]*p - M[j] >= 0 j-i 盡量大
// 123456789*p m 小->大
// 123456789 M
//思路: 先排序,再找最大值
代碼
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int main(){
int n;
float p;
int seq[100005];
int res = 1; // 這里初始化為0會造成后面數組越界,開始的算法不會有這個問題,改變算法后此處不改導致錯誤產生
cin >> n >> p;
for (int i = 0; i < n; ++i) {
scanf("%d",&seq[i]);
}
sort(seq, seq+n);
// 這個算法是不斷縮小范圍,每次都需要從最大開始進行縮小。這個算法會導致超時
// for (int i = 0; i < n; ++i) {
// for (int j = n-1; j > i + res - 1; --j) {
// if (seq[j] <= product[i]) {
// if (j - i + 1 > res) {
// res = j - i + 1;
// }
// break;
// }
// }
// }
// 這個算法是不斷擴大范圍,每次擴大的范圍越來越小,因為滿足條件的值是在小范圍內波動的。
for (int i = 0; i < n; ++i) {
for (int j = i+res-1; j < n;++j){
if (seq[j] <= seq[i]*p) {
if (j-i+1 > res) {
res = j - i + 1;
}
}else{
break;
}
}
}
printf("%d\n",res);
}
過程資料
注意:
- 純整數運算在數據較大時容易越界導致結果錯誤。應當將其轉化為浮點運算。在此題中即把 p 定義為浮點數。
- 改變算法后,使用的變量的初值可能會需要改變,要對變量的邊界改變情況敏感。例如此題中的res初值。
測試點:
- 數組越界導致1、3測試點錯誤。
- 最后一個測試點是大數,m*p 會超出整數范圍,不能使用整數進行計算。