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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章