PAT B1030/A1085 完美数列

给一个整数数列和正整数p,设这个数列中最大值M,最小值m,如果有M<=m*p,则称这个数列为完美数列,给一个p和一些正整数,从里面选择尽可能多的数,使他们构成一个完美数列,并输出最多可以选择的数字个数。
分析:
从左至右扫描序列对其中的每一个数a[i]。在[i+1,n-1]二分查找第一个超过a[i]*p数的位置j,这样j-i就是对位置i来说满足a[j]<=a[i]*p的最远长度。所有j-i的最大值即为所求答案。时间复杂度为O(lnn)。

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 100010;
int a[maxn], n,p;
//在[i+1,n-1]的范围内查找第一个大于x的位置
int binarySearch(int i,long long x) {
    if (a[n - 1] <= x) return n;//最大的一个元素都小于m*p,则这一整个数列就都满足。
    int l = i + 1, r = n - 1,mid;
    while (l < r) {
        mid = (l + r) / 2;
        if (a[mid] <= x) {
            l = mid + 1;
        }
        else {
            r = mid;
        }
    }
    return l;//在结束时,l与r相等
}
int main() {
    scanf("%d%d", &n, &p);
    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    sort(a, a + n);        //递增排序
    int ans = 1;          //最大长度
    for (int i = 0; i < n; i++) {
        //在a[i+1]~a[n-1],内查找第一个超过a[i]*p的数
        int j = binarySearch(i, (long long)a[i] * p);
        ans = max(ans, j - i);//更新最大长度。
    }
    printf("%d\n", ans);
    return 0;
}

 

posted @ 2021-04-17 18:27  银发制御  阅读(66)  评论(0)    收藏  举报