簡體   English   中英

數論算法。 該細分市場上的大多數除數

[英]Number theory algorithms. Most divisors on the segment

我正在尋找一種有效的算法來解決以下問題。 d(n)表示的正除數的數n其中n是正整數。 我們得到了一些1 <= a <= b <= 10^18 ,任務是在段[a..b]上找到d最大值,並且(可能我們需要更復雜的算法)來查找最大化d值的數字。

前段時間我在免費訪問中找到了以下代碼: http//ideone.com/qvxPj

unsigned long long n, res;
int p, primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 51, 53, 59, 61, 67, 71};

unsigned long long mul(unsigned long long a, unsigned long long b){
    unsigned long long res = 0;

    while (b){
        if (b & 1LL) res = (res + a);
        if (res >= n) return 0;
        a = (a << 1LL);
        b >>= 1LL;
    }

    return res;
}

void backtrack(int i, int lim, unsigned long long val, unsigned long long r){
    if (r > res) res = r;
    if (i == p) return;

    int d;
    unsigned long long x = val;

    for (d = 1; d <= lim; d++){
        x = mul(x, primes[i]);
        if (x == 0) return;
        backtrack(i + 1, d, x, r * (d + 1));
    }
}

int main(){    
    p = sizeof(primes) / sizeof(int);

    while (scanf("%llu", &n) != EOF){
        res = 0;
        backtrack(0, 100, 1, 1);
        printf("Maximum number of divisors of any number less than %llu = %llu\n", n, res);
    }
    return 0;
}

如果有人向我解釋它是如何工作的,我將非常高興,因為(至於我)這個程序運行得非常快。

在此先感謝您的幫助。

它迭代所有數字,如下所示:

num = P1^D1 * P2^D2 * P3^D3 * ... * Ps^Ds
constraints:
  Pi <= 71
  1 <= Di <= 100
  sequence (Pi) is a sorted list of first s primes
  sequence (Di) is nonincreasing
  num <= n

讓我們檢查第一個約束。 假設最小最優數具有素因子q> 71 如果任何質數p <= 71未在此數中使用的話,可以在相同的功率p替換Q值 顯然,除數的數量將保持不變,但數量會減少 - >矛盾。 然后沒有未使用的素數低於71.但是所有素數高達71的產品已經非常龐大,我們考慮的數量必須大於64位n 那是不可能的。

現在讓我們解釋第二個和第三個約束。 假設我們的最小最優數在其因子分解中具有素數q ,但是沒有一些素數p ,其中p <q 然后我們可以用p以相同的順序替換q ,數字將具有相同數量的除數,但它會變得更少 - >矛盾。 這意味着所尋求的最優(最小)數的因式分解中的所有素數必須恰好是第一個素數。 使用的素數組中不能有空洞。 BTW, Di <= 100是顯而易見的,因為即使2 ^ 100也不適合64位整數。

現在我們要解釋第四個約束。 假設某些i的 D [i] <D [i + 1] 然后,我們可以取代P [I] ^ d [I] * P [I + 1] ^ d [I + 1] P [I] ^ d [I + 1] * P [I + 1] ^ d [I ] ,數字會變小。 例如,用5 ^ 3 * 7 ^ 2替換5 ^ 2 * 7 ^ 3:除數的數量相同,但結果更小。 顯然,如果我們搜索最小的最優數,我們也可以安全地假設這個條件。

現在讓我們考慮一下代碼。 mul是一個計算ab的乘積的小函數。 它是通過一個有趣的二進制程序計算的。 此過程的主要原因是:如果乘積大於n ,則函數返回0.此過程僅防止溢出,否則可能發生。

最后,我們得backtrack 這是一種通常的遞歸搜索。 val是當前數字, r是它的除數數, i顯示我們現在要添加的素數的索引,每個素數的lim限制功率為100.在一開始你看到當前最佳答案的更新(存儲在res )和硬停止條件(使用的所有質數)。

然后有一個循環檢查當前素數的每個冪。 它從功率1開始,因為禁止零功率。 它維持x當前數字,並在每次迭代時將其乘以Pi以增加功率。 如果x大於n ,則立即停止。 最后,它調用自己以搜索下一個素數。

作為@stgatilov答案的補充,我將證明選擇將素數限制為少於或等於71的素數。

我使用稍微修改過的代碼版本來記錄最大數量的除數。 對於1000000000000000000或999999999999999999,我得到:

897612484786617600 = 2 8 * 3 4 * 5 2 * 7 2 * 11 * 13 * 17 * 19 * 23 * 29 * 31 * 37

共有103680個除數。

這意味着對於所有18個十進制數字的數字,沒有涉及大於37的素數是找到具有最大除數的整數。

暫無
暫無

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

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