簡體   English   中英

N 數的除數之和

[英]The sum of the divisors of an N number

找到然后求和從 1 到 N 的所有除數。
主要問題是,此代碼在高數字下運行非常糟糕。

以下代碼取自: https : //www.geeksforgeeks.org/sum-divisors-1-n

        static int divisorSum(int n)
        {
            int sum = 0;

            for (int i = 1; i <= n; ++i)
            {
                for (int j = 1; j * j <= i; ++j)
                {
                    if (i % j == 0)
                    {
                        if (i / j == j)
                            sum += j;
                        else
                            sum += j + i / j;
                    }
                }
            }
            return sum;
        }

基於@Joel 解決方案,我只是對其進行了改進:

static long divisorSum(int n)
{
   long sum = 0;
   for (long i = 1; i <= n/2; ++i)
      sum += i * (n / i);
   sum += (n/2+1+n)*(n-n/2)/2; // It's a sum of an arithmetic progression‏‏‏‏
   return sum;
}

對於i > n/2 ,表達式i * (n / i)就是簡單的i (因為n/i = 1),所以我們可以通過計算n/2 + 1n之間的所有數字的總和來獲得一個等差數列。 它會運行得更快,盡管它也是O(n)

無需使用各種集合,因為您將所有內容匯總在一起,無需考慮重復項。 我不認為有辦法解決這個問題,這是一個完美的O(n) ,但這是我能想到的最接近的:

int sum = 0;

for (int i = 1; i <= n; i++) 
{
    double sqrt = Math.Sqrt (i);

    for (int j = 1; j <= sqrt; j++) 
    {
        if (i % j == 0) 
        {
            sum += j;

            if (j != sqrt)
                sum += i / j;
        }
    }
}

除數是成對的,所以不需要每次都一直到i (例如1 * 1010 * 1是相同的)。 您可以計算i的平方根(“中點”),並節省時間,因此它不是O(n^2) ,但也不是完美的O(n)

你可以做這樣的事情O(n)

static long divisorSum(int n)
{
    long sum = 0;
    for (long i = 1; i <= n; ++i)
        sum += i * (n / i);
    return sum;
}

static void Main(string[] args)
{
    int val = 129999;
    Console.WriteLine(divisorSum(val));
    Console.ReadLine();
}

測試:

12999 => 8ms
129999 => 25ms
2147483647 => 18770ms (Max Int32 value)

int val = 129999;
int maxInt = int.MaxValue;

//val (129999)
var watch = System.Diagnostics.Stopwatch.StartNew();
Console.WriteLine(divisorSum(val));
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine(elapsedMs); //25ms

//MaxInt (2147483647)
watch = System.Diagnostics.Stopwatch.StartNew();
Console.WriteLine(divisorSum(maxInt));
watch.Stop();
elapsedMs = watch.ElapsedMilliseconds; //18770ms 
Console.WriteLine(elapsedMs);
Console.ReadLine();

暫無
暫無

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

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