pat乙级 1030 完美数列
给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤mp,则称这个数列是完美数列。
现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
输入格式:
输入第一行给出两个正整数 N 和 p,其中 N(≤105)是输入的正整数的个数,p(≤109)是给定的参数。第二行给出 N 个正整数,每个数不超过 109。
输出格式:
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
输入样例1:
10 8
2 3 20 4 5 1 6 7 8 9
输出样例1:
8
总结:
按从小到大顺序排好
外循环1:
1 2 3 4 5 6 7 8 9 20 max<=min*p ? (NO) min指针移到下一位
↑ ↑
min max
1 2 3 4 5 6 7 8 9 20 max<=min*p ? (NO) min指针移到下一位
↑ ↑
min max
1 2 3 4 5 6 7 8 9 20 max<=min*p ? (Yes) 记录有8个数
↑ ↑
min max
外循环2:
1 2 3 4 5 6 7 8 9 20 max<=min*p ? (NO) min指针移到下一位
↑ ↑
min max
1 2 3 4 5 6 7 8 9 20 max<=min*p ? (YES) 记录有8个数,(8<8)不更新
↑ ↑
min max
外循环3:
1 2 3 4 5 6 7 8 9 20 max<=min*p ? (YES) 记录有8个数,(8<8)不更新
↑ ↑
min max
外循环4:
1 2 3 4 5 6 7 8 9 20 max-min指针之间只有7个数 小于8,退出循环,结束
↑ ↑
min max
改进:寻找min指针可以用二分法查找
外循环1:
1 2 3 4 5 6 7 8 9 20 max<=mid*p ? (YES) mid指针到左半部分找
↑ ↑ ↑↑
sort_min mid sort_max,max
1 2 3 4 5 6 7 8 9 20 max<=mid*p ? (NO) min指针移到右半部分
↑ ↑ ↑ ↑
mid sort_max max
sort_min
1 2 3 4 5 6 7 8 9 20 max<=mid*p ? (Yes) mid指针到左半部分找
↑↑ ↑ ↑
sort_min sort_max max
mid
1 2 3 4 5 6 7 8 9 20 max<=mid*p ? (Yes) mid指针到左半部分找
↑↑↑ ↑
max
下一步因为sort_min>sort_max 退出内循环 ,mid指向3; 判断max<=mid*p ?(YES) 更新个数8
sort(v.begin(), v.end());
int max = 0;
int max_flag = v.size() - 1;
for (; (max_flag >= 0) && (max_flag + 1 > max); max_flag--){
int sort_max = max_flag;
int sort_min = 0;
int mid;
while (sort_min <= sort_max) 二分查找min指针
{
mid = (sort_max + sort_min) / 2;
if (v[max_flag] < v[mid] * p){
sort_max = mid - 1;
}
else if(v[max_flag] > v[mid] * p)
{
sort_min = mid + 1;
}
else{
break;
}
}
if(v[max_flag] <= v[mid] * p){ 得到min指针后一定要再判断一次(v[max_flag] <= v[mid] * p) 如果符合才更新个数
if (max_flag - mid + 1> max){
max = max_flag - mid+ 1 ;
}
}
}
AC代码:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
int n;
double p;
cin >> n >> p;
vector<double> v;
for (int i = 0; i < n; i++){
double input;
cin >> input;
v.push_back(input);
}
sort(v.begin(), v.end());
int max = 0;
int max_flag = v.size() - 1;
for (; (max_flag >= 0) && (max_flag + 1 > max); max_flag--){
int sort_max = max_flag;
int sort_min = 0;
int mid;
while (sort_min <= sort_max)
{
mid = (sort_max + sort_min) / 2;
if (v[max_flag] < v[mid] * p){
sort_max = mid - 1;
}
else if(v[max_flag] > v[mid] * p)
{
sort_min = mid + 1;
}
else{
break;
}
}
if(v[max_flag] <= v[mid] * p){
if (max_flag - mid + 1> max){
max = max_flag - mid+ 1 ;
}
}
}
cout << max;
system("pause");
return 0;
}