PAT乙级.1030. 完美数列(25)

来源:互联网 发布:mac制作铃声怎么改时间 编辑:程序博客网 时间:2024/05/18 01:59

1030. 完美数列(25)


题目

给定一个正整数数列,和正整数p,设这个数列中的最大值是M,最小值是m,如果M <= m * p,则称这个数列是完美数列。

现在给定参数p和一些正整数,请你从中选择尽可能多的数构成一个完美数列。

输入格式

输入第一行给出两个正整数N和p,其中N(<= 105)是输入的正整数的个数,p(<= 109)是给定的参数。第二行给出N个正整数,每个数不超过109。

输出格式

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

输入样例

10 8
2 3 20 4 5 1 6 7 8 9

输出样例

8

PAT链接


思路

1.读取数列,并用sort()将数列排序,形成递增序列
2.从0开始遍历所有元素,找到满足M <= m*p的最后的一个数的下标,与起始下标之间的下标数即为可选择的个数,不断更新结果,从而取得最大。


代码

version1.0(自己写的upper)

/*** @tag     PAT_B_1030* @authors R11happy (xushuai100@126.com)* @date    2016-9-5 16:44-17:44* @version 1.0* @Language C++* @Ranking  715/651* @function null*/#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>using namespace std;const int Max = 1e5;int upper(int num[], int left, int right, long long x){    int mid;    while(left < right)    {        mid = left + (right - left)/2;        if(num[mid] > x)        {            right = mid;        }        else        {            left = mid + 1; //不能是left = mid, 不然有可能死循环        }    }    return left-1;  //返回第一个满足M>x的数(left是最后一个满足M<=x的数)}int main(int argc, char const *argv[]){    int num[Max+10];    int N;    long long x, p;    int res, Max = 0;    scanf("%d %d",&N, &p );    for(int i = 0; i<N; i++)    {        scanf("%d", &num[i]);    }    sort(num, num+N);   //组成递增序列    for(int i = 0; i < N; i++)    {        x = num[i] * p; //这里,x可能达到18位数,但要保证x存储正确的long long 类型,p也必须是long long 类型        res = upper(num, i, N, x) - i + 1;        if(res > Max)   Max = res;    }    printf("%d\n",Max );    return 0;}

version2.0(调用STL的upper_bound函数)

/*** @tag     PAT_B_1030* @authors R11happy (xushuai100@126.com)* @date    2016-9-5 16:44-17:44* @version 1.0* @Language C++* @Ranking  715/651* @function null*/#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>using namespace std;const int Max = 100000; //段错误,先判断数组是不是开小了int main(int argc, char const *argv[]){    int num[Max+10];    int N;    long long x, p;    int res, maxn = 0;    scanf("%d %d",&N, &p );    for(int i = 0; i<N; i++)    {        scanf("%d", &num[i]);    }    sort(num, num+N);   //组成递增序列    for(int i = 0; i < N; i++)    {        x = num[i] * p; //这里,x可能达到18位数,但要保证x存储正确的long long 类型,p也必须是long long 类型        res = upper_bound(num+i,num+N, x) - num;    //第一个满足M>m*p的前一位为最后一个满足M<=m*p的,减一个1,再加一个1,相当于抵消        if(res > maxn)   maxn = res;    }    printf("%d\n",maxn );    return 0;}

收获

  1. x = num[i] * p;
    其中x已被声明为long long 类型,若要保证x结果正确,还需将num[i]或p其中之一声明为long long类型,不然会得到错误结果

2.段错误先想数组是不是开小了,答案错误要想着是不是要用long long 类型,特别是给出的条件在9位左右,后面涉及乘法时候一定要注意

3.lower_bound(first, last, val)
用来寻找在数组或容器的[first, last)范围内第一个值大于等于val的元素的位置,如果是数组,则返回该位置的指针,如果是容器,则返回该位置的迭代器

4.upper_bound(first, last, val)
用来寻找在数组或容器的[first, last)范围内第一个值大于val的元素的位置,如果是数组,则返回该位置的指针,如果是容器,则返回该位置的迭代器

5.由于返回的是指针,如果只是想获得欲查元素的下标,就可以不使用临时指针,而直接令返回值减去数组首地址即可。

0 0
原创粉丝点击