簡體   English   中英

尋找素數

[英]Finding a Prime Numbers

我有一個長度為N=10^5的數組,每個索引1 <= i <= n

我必須計算A[j]-A[i] and (ji) is prime and j>i

這是我的代碼:

for(int i=1;i<=n;i++){

    for(int j=0;j<prime.size();j++){

         int x = prime.get(j);

         if(x+i>n) break;
         ans+= A[x+i]-A[i];
    }
}

我應該如何使這項工作更快? 我認為時間復雜度為O(N * prime.size)

首先,我將重述您的問題,以便說出我相信您想要實現的目標。 您可能正在尋找形式為A[j]-A[i] ,其中(ji)是“正”素數且1<=i<j<=N 考慮到這一點...

我們計算將A[k]加到總和(用p表示)的次數, A[k]從總和減去A[k] (用m表示)的次數。 好吧, m等於區間[1,Nk]的素數,而p等於區間[1,k-1]的素數。 如果您不相信我,請逐步模擬代碼的功能。 然后,您可以執行以下操作:

S = 0
for k = 1 to N do
    S = S + (p(k) - m(k)) * A[k]
endfor

現在,我們需要找到一種方法來有效確定間隔[1,N]每個k pm 我看到您已經構建了看似素數的有序列表。 因此,要回答“間隔[1,t]多少個素數?”形式的查詢。 您可以在該列表上對t執行二進制搜索。 這將使復雜度降低到O(N*log(prime.size))

或者,您可以預先計算“間隔[1,t]多少個素數?”形式的查詢答案。 您需要一個大小為N的額外數組nrPrimesLessThan來保留結果,進行如下操作以計算其值:

count = 0
for i = 1 to N do
    if i < prime.get(count) then
        nrPrimesLessThan[i] = count
    else
        count = count + 1
        nrPrimesLessThan[i] = count
    endif
endfor

預計算部分需要O(N)步驟,但是現在一個查詢需要O(1)步驟,因此計算總和需要O(N)步驟。 總的來說,線性時間為N

從您的代碼示例判斷,您想要對數組中所有值對的差值求和,而這些值對的索引差為質數。 您已經有了素數的數組。

下圖顯示了如何減去和添加元素:

        0   1   2   3   4   5   6   7   8   9

        -       +   +       +       +                0
            -       +   +       +       +            1
                -       +   +       +       +        2
                    -       +   +       +            3
                        -       +   +       +        4
                            -       +   +            5
                                -       +   +        6
                                    -       +        7
                                        -            8
                                            -        9

+表示將元素添加到總和中。 -表示從總和中減去元素。 這不是一個單一的減法。 減法發生在其左邊的每個加法上,因此A[0]被減去4次。 永遠不會添加。

另一方面,從不減去A[9] ,而是相加四次。 通常,將每個元素減去行中存在的加號的次數,將其相加得到的次數與列中存在的加號的次數相同。 這里有一個對稱性:

add[i] = sub[N - i - 1]

從零開始的索引。 add[i]的值是什么? 素數小於或等於i

這是一個代碼示例,其中add數組稱為m

int psum2(const int A[], int n)
{
    int sum = 0;

    int m[n];
    int j = 0;
    int k = 0;

    for (int i = 0; i < n; i++) {
        if (i == prime[j]) {
            k++;
            j++;
        }
        m[i] = k;
    }

    for (int i = 0; i < n; i++) {
        sum += (m[i] - m[n - i - 1])  * A[i];
    }

    return sum;
}

數組m總是相同的,如果您需要更頻繁地執行總和,可以對其進行預先計算。 該算法為O(n)。

這個問題也與素數無關。 上面的方法適用於所有條件差的和,其中索引的差必須包含在一組特定的數字中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM