PAT-B 1030. 完美数列

题目内容:

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

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

输入格式:

输入第一行给出两个正整数 N p ,其中 N105 是输入的正整数的个数, p109 是给定的参数。第二行给出 N 个正整数,每个数不超过 109

输出格式:

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

输入样例:

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

输出样例:

8

思路分析:

本题思路是从双层for循环,逐个组合验证的方法优化得来的。

  • 对于任何两个满足 Mmp 关系的数 M m 对应的最长序列就是所有在 M m 之间的所有数。所以我先排序,后分析长度。
  • 对于已知符合要求的最长序列,其长度为 count 。那么下面需要验证的就是所有长度大于 count 的序列。

验证时外层循环控制变量为 i,标记被验证序列的开始位置。内层循环的控制变量为 j 标记被验证序列的结束位置。变量 count 记录已知最长的完美数列长度。所以对于每一个 iji+count 开始验证。i 在距离输入数据的最后元素距离为 count 时停止验证,因为 i 继续增大,得出的完美数列长度已经不可能超过已知,没有验证的必要。

代码:

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

int comp(const void *a, const void *b)
{
    return *(int*)a-*(int*)b;
}

int main()
{
    int n = 0, p = 0, count = 0, temp = 0;
    scanf("%d%d", &n, &p);
    int ary[n];

    for (int i = 0; i < n; i++)
        scanf("%d", ary+i);

    qsort(ary, n, sizeof(int), comp);

    for (int i = 0; count != n && i < n - count; i++) { // 已知完美数列长度达到最大可能时,退出全部循环
        for (int j = i + count; j < n; j++) { // 待验证数列结尾部分从i+count开始
            if (j == n-1 || ary[j+1] > (long long)ary[i] * p) { 
                if (ary[j] <= (long long)ary[i] * p) { 
                // 当此时的ij组合满足完美数列,但下个j,不满足完美数列要求,此时的ij对为对于当前i的最大可能完美数列
                    temp = j - i + 1; // 计算当前数列长度
                    count = (temp > count) ? temp : count; // 跟已知的对比,取更大的一个
                }
                break;
            }
        }
    }

    printf("%d", count);

    return 0;
}

点这里进入试题网页

你可能感兴趣的:(pat,乙级,简洁代码)