【PAT (Basic Level) Practice】——【二分】1030 完美数列

一【题目难度】

  • 乙级

二【题目编号】

  • 1030 完美数列 (25 分)

三【题目描述】

  • 给定一个正整数数列,和正整数 p p p,设这个数列中的最大值是 M M M,最小值是 m m m,如果 M ≤ m p M≤mp Mmp,则称这个数列是完美数列。
  • 现在给定参数 p p p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。

四【题目示例】

  • 输入格式:
    输入第一行给出两个正整数 N N N p p p,其中 N ( ≤ 1 0 5 ) N(≤10^5 ) N105是输入的正整数的个数, p ( ≤ 1 0 9 ) p(≤10^9 ) p109是给定的参数。第二行给出 N N N 个正整数,每个数不超过 1 0 9 10^9 109

  • 输出格式:
    在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。

  • 输入样例:
    10 8
    2 3 20 4 5 1 6 7 8 9

  • 输出样例:
    8

五【解题思路】

  • 这道题的重点是理解好题意,题目的意思是给你一些数字,让你从这里找出最大 M M M的和最小的 m m m,使其满足 M ≤ m p M≤mp Mmp,并且还要求整个结果数组达到最长,既然这样,对这一系列数字进行排序再找出最大最小比较好,所以首先对其按照从小到大排序,然后再逐一根据题目条件搜索,但是如果采用 O ( N 2 ) O(N^2) O(N2)的循环搜索肯定会超时,所以既然有序,首先想到二分法,这个判断条件就是 M > m p M>mp M>mp,这时前一个就是满足题目要求最长的(因为数组已经有序),其后面的肯定都不符合要求,其次还要注意,结果最少都是1,因为最少有一个满足要求,所以每次更新找最大的即可

六【最终得分】

  • 25分

七【代码实现】

#include<stdio.h>
#include<stdlib.h>

int max_1030_PerfectSequence(int a,int b)
{
    return a > b ? a : b;
}

int cmp_1030_PerfectSequence(const void *a,const void *b)
{
    return *(int *)a > *(int *)b ? 1 : -1;
}

int binarySearch(int* nums,int i,int n,long long mp)
{
    if(nums[n-1] < mp)
    {
        return n;
    }
    int left = i + 1;
    int right = n - 1;
    while(left < right)
    {
        int mid = (left +right) / 2;
        if(nums[mid] <= mp)
        {
            left = mid + 1;
        }
        else
        {
            right = mid;
        }
    }
    return left;
}

int main()
{
    int n,p,res = 1;
    scanf("%d %d",&n,&p);
    int* nums = (int *)calloc(n,sizeof(int));
    for(int i = 0;i<n;i++)
    {
        scanf("%d",&nums[i]);
    }
    qsort(nums,n,sizeof(int),cmp_1030_PerfectSequence);
    for(int i = 0;i<n;i++)
    {
        int index = binarySearch(nums,i,n,(long long)nums[i] * p);
        res = max_1030_PerfectSequence(res,index - i);
    }
    printf("%d",res);
    return 0;
}

八【提交结果】

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IronmanJay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值