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
作者: CAO, Peng
单位: Google
时间限制: 200 ms
内存限制: 64 MB
方法一: 暴力 + 优化
#include<iostream>
#include<algorithm>
using namespace std;
long long int a[100009];
int main(void){
int n,p;
while( scanf("%d%d",&n,&p)!=EOF){
for( int i=0;i<n;i++){
scanf("%lld",&a[i]);
}
sort(a,a+n);
int ans =0,tmp;
for( int i=0;i<n;i++){
if( i + ans >n )
continue;
tmp = ans;
for( int j=i+ans;j<n;j++ ){
if( a[j] <= ( long long int ) a[i] * p ){
tmp++;
continue;
}
else break;
}
ans = max( ans,tmp);
}
printf("%d\n",ans);
}
return 0;
}
方法二: 尺取
#include<iostream>
#include<algorithm>
using namespace std;
long long int a[100009];
int main(void){
int n,p;
while( scanf("%d%d",&n,&p)!=EOF){
for( int i=0;i<n;i++){
scanf("%lld",&a[i]);
}
sort(a,a+n);
int ans=0;
int left=0,right=0;
while( left < n && right < n ){
while( ( long long int )a[left] * p >= a[right] && right <n ){
right++;
}
ans = max( ans , right - left );
left++;
}
printf("%d\n",ans);
}
return 0;
}
方法三: 二分
#include<iostream>
#include<algorithm>
using namespace std;
long long int a[100009];
int n,p;
int cal( int left ,int right ){
int mid ;
long long int temp= (long long int )a[left] * p;
if(a[n-1]<=temp)
return n;
while( left < right ){
mid = left + (right-left)/2;
if( a[mid] <= temp){
left=mid+1 ;
}
else right = mid;
}
return left;
}
int main(void){
while( scanf("%d%d",&n,&p)!=EOF){
for( int i=0;i<n;i++){
scanf("%lld",&a[i]);
}
sort(a,a+n);
int ans =1;
for( int i=0;i<n;i++){
int t =cal(i,n-1) -i;
ans = max( ans , t);
}
printf("%d\n",ans);
}
return 0;
}