PAT乙级1030 完美数列 (25分)看不懂你来找我!(算法优化)

原题链接https://pintia.cn/problem-sets/994805260223102976/problems/994805291311284224
1030 完美数列 (25分)
给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤mp,则称这个数列是完美数列。

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

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

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

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

输出样例:
8
分析:此题主要卡超时,需要算法的优化:
首先要排序,直接用两个循环遍历,会超时,如何优化?假设第二重循环第一次遍历结束后的位置是p,我们可以发现第二重循环如果每次从最小数开始遍历,由于从第二次遍历开始一直到p的几个数一定小于pmin,所以再次将这前几个数进行判断是否小于pmin是无效操作,因此需要记录每次遍历结束后的位置,下一组遍历从上次遍历结束的位置开始和p*min比较。

#include<bits/stdc++.h>
using namespace std;

int main()
{
    iostream::sync_with_stdio(0);
    int N;
    long long p;
    cin>>N>>p;
    int i,j,k;
    long long a[N];
    long long t,ans=0,cnt=0,position=0;
    for(i=0;i<N;i++)
    {
        cin>>a[i];
    }
    sort(a,a+N);
    for(i=0;i<N;i++)
    {
       t=a[i]*p;
       for(j=position;a[j]<=t&&j<N;j++)//从上一次结束的position开始,一定要记得加上<N,不然如果所有的数都小于min*p这种情况会错
       {
           cnt++;
       }
       if(cnt>ans)
        ans=cnt;
        if(N-i<=ans)//如果从i开始到结束的数的数量都小于当前的ans,此时ans就是最大的
            break;
        cnt--;
        position=j;//记录结束位置
    }
    cout<<ans;
    return 0;
}
发布了11 篇原创文章 · 获赞 4 · 访问量 161

猜你喜欢

转载自blog.csdn.net/tongjingqi_/article/details/105600273