PAT-B 真题- 1030. 完美数列/A1085 Perfect Sequence

发布于 / PAT-乙级 / 0 条评论

原题干:

给定一个正整数数列,和正整数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

这道题给的数比较大,用int亲测不会通过,这里我使用的是long long。

先排序,在从前和从后分别遍历。如果全部遍历亲测会超时。

这里我们只遍历部分就可以。代码如下

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int main(){
  int n;
  long long p;
  cin >> n >> p;
  vector<long long int> a(n);
  for (int i = 0; i < n; i++)
    cin >> a[i];
  sort(a.begin(), a.end());
  int result = 1;
  for (int i = 0; i < n - 1; i++) {
    for (int j = i + result; j < n; j++) {
      if (a[j] > a[i] * p) break;
      result = max(result, j - i + 1);
    }
  }
  cout << result;
  return 0;
}

另外一种办法是使用二分法,遍历排好序的数组,对于每一个值,使用二分找到小于等于它的上限(p倍)的位置,然后计算距离即可得到序列元素个数。

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int main(){
  size_t N, p, arr[maxn] = {0}, _max_len = 0;
  cin >> N >> p;
  for(size_t i = 0; i < N; i++) cin >> arr[i];
  sort(arr, arr + N);
  for(size_t i = 0; i < N; i++){
    size_t high = arr[i] * p;  //上限为最小值*p
    size_t* _high = lower_bound(&arr[i], arr + N, high);
    if(_high == arr + N) _high--;  //如果没找到 
    if(*_high > high) _high--;
    _max_len = max(_max_len, (size_t)(_high - &arr[i] + 1));
  }
  cout << _max_len << endl;
  return 0;
}

转载原创文章请注明,转载自: 斐斐のBlog » PAT-B 真题- 1030. 完美数列/A1085 Perfect Sequence
目前还没有评论,快来抢沙发吧~