1030 完美数列
一、题目
给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M M M,最小值是 m,如果 M ≤ m p M≤mp M≤mp,则称这个数列是完美数列。
现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
二、输入输出
输入格式
输入第一行给出两个正整数 N 和 p,其中 N( ≤ 1 0 5 ≤10^5 ≤105)是输入的正整数的个数,p( ≤ 1 0 9 ≤10^9 ≤109)是给定的参数。第二行给出 N 个正整数,每个数不超过 10 9 10^9 109 。
输出格式
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
三、样例
输入样例
10 8
2 3 20 4 5 1 6 7 8 9
输出样例
8
四、题目分析
首先读入数据,对数据进行排序,依次遍历最小值,找到小于
m
p
mp
mp的数量(即找到第一个大于
m
p
mp
mp的数),输出其中的最大值。由于对数据已经进行排序,在进行查找第一个大于mp的数时,使用顺序查找会超时,因此需要采用二分查找,使用函数lower_bound()
、upper_bound()
。还需要主要数据类型,使用int会溢出。
五、代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
long long int p;
int num_max=0;
cin>>n>>p;
vector<long long int> v;
for(int i=0;i<n;i++){
long long int x;
cin>>x;
v.push_back(x);
}
sort(v.begin(),v.end());
for(int i=0;i<v.size();i++){
long long int x=v[i]*p;
int num=upper_bound(v.begin()+i,v.end(),x)-(v.begin()+i);
if (num>num_max)
num_max=num;
}
cout<<num_max;
}
六、总结
1.数据类型的存储范围
-
整型数据存储空间及数值范围(Visual C++)
类型 名称 字节数 数值范围 数值范围(二进制) 大致范围(十进制) [signed] int 有符号基本整型 4 [-2,147,483,648 ~ 2,147,483,647] − 2 31 -2^{31} −231~ ( 2 31 − 1 ) (2^{31}-1) (231−1) − 1 0 9 -10^{9} −109~ 1 0 9 10^{9} 109 unsigned int 无符号基本整型 4 [0 ~ 4,294,967,295] 0 ~ ( 2 32 − 1 ) (2^{32}-1) (232−1) 0 0 0~ 1 0 9 10^{9} 109 [signed] short [int] 有符号短整型 2 [-32,768 ~ 32,767] − 2 15 -2^{15} −215~ ( 2 15 − 1 ) (2^{15}-1) (215−1) − 1 0 5 -10^{5} −105~ 1 0 5 10^{5} 105 unsigned short [int] 无符号短整型 2 [0 ~ 65,535] 0 ~ ( 2 16 − 1 ) (2^{16}-1) (216−1) 0 ~ 1 0 5 10^{5} 105 [signed] long [int] 有符号长整型 4 [-2,147,483,648 ~ 2,147,483,647] − 2 31 -2^{31} −231~ ( 2 31 − 1 ) (2^{31}-1) (231−1) − 1 0 9 -10^{9} −109~ 1 0 9 10^{9} 109 unsigned long [int] 无符号长整形 4 [0 ~ 4,294,967,295] 0 ~ ( 2 32 − 1 ) (2^{32}-1) (232−1) 0 ~ 1 0 9 10^{9} 109 [signed] long long [int] 有符号双长整型 8 [-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807] − 2 63 -2^{63} −263~ ( 2 63 − 1 ) (2^{63}-1) (263−1) − 1 0 18 -10^{18} −1018~ 1 0 18 10^{18} 1018 unsigned long long [int] 无符号双长整型 8 [0 ~ 18,446,744,073,709,551,615] 0 ~ ( 2 64 − 1 ) (2^{64}-1) (264−1) 0 ~ 1 0 19 10^{19} 1019
2.二分查找函数
-
lower_bound( )
lower_bound( begin,end,num)
从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。
-
upper_bound( )
upper_bound( begin,end,num)
从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end
-
注意事项:
- 1.二分查找需要先进行排序
- 2通过返回的地址减去起始地址begin,得到找到数字在数组中的下标
- 3begin、end可以是指针,也可以是迭代器