1. 程式人生 > >PAT乙級—1030. 完美數列(25)-native

PAT乙級—1030. 完美數列(25)-native

給定一個正整數數列,和正整數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

思路:首先p與最小數相乘可能會超出int範圍,所以這裡用double,其次我們應該先將陣列排序以方便計算,然後我們用雙重for迴圈查詢,查詢的思路是從第一個元素作為最小數,開始往後找最大數,直到不符合條件,記錄下此時的長度,然後將第二個元素作為最小數,再繼續找,最後比較長度的最大值並輸出,但是這樣會超時,所以我們要對她進行優化,減少不必要的迴圈,優化的思路如下:

首先我們同樣保持第一個for迴圈遍歷最小值,在第二個for迴圈中我們將j置為前一個元素作為最小數時候的長度,這樣就減少了小於上一次的不必要的for迴圈,j依然小於 N,用一個if判斷是否符合條件,用另一個if判斷此次是否大於上次的長度,比如說我們把樣例中的資料已經排好序:1 2 3 4 5 6 7 8 9 20 ,此時我們將array[0]作為最小數,依次向後遍歷,最大數j-最小數i+1即為數列的長度,最終找到8為最大的數,此時數列長度count為8,在將a[1]作為最小數的時候,我們直接將j置為1+8為9,直接比較a[1]和a[9]作為最小最大值得時候是否滿足,不滿足則a[1]最為最小數的時候並不能使數列變得更長,則繼續再看a[2],這樣等到有大於8的時候再更新,就可以了。

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
    int N,count=0;
    double p,array[100010];;
    scanf("%d%lf",&N,&p);
    for(int i=0;i<N;i++)
        scanf("%lf",&array[i]);
    sort(array,array+N);
    for(int i=0;i<N;i++)            //遍歷,將a[i]作為最小數
for(int j=i+count;j<N;j++){ //j置為要滿足可以更新數列長度的值,減少迴圈次數 if(array[j]>array[i]*p) //如果不滿足條件了,則將下一個元素最為最小值 break; if(j-i+1>count) //如果此次的長度大於上一次,更新數列長度 count=j-i+1; } printf("%d",count); return 0; }