N'ye karşılık gelen tüm Dört Kare kombinasyonlarını ne kadar hızlı bulabiliriz?


12

Stack Overflow'da ( burada ) bir soru soruldu :

Tamsayıdır bir göz önüne alındığında , tam sayı değerlerinin tüm muhtemel kombinasyonları çıktısını bir , B , C ve D denklemi çözmek A 2 + B 2 + C 2 + D 2 = N .NA,B,CDA2+B2+C2+D2=N

Bu soru elbette Bachet'in sayı teorisindeki Konjonktürü ile ilgilidir (bazen kanıtı nedeniyle Lagrange'ın Dört Kare Teoremi olarak adlandırılır). Tek bir çözümün nasıl bulunacağını tartışan bazı makaleler var, ancak belirli bir N için tüm çözümleri (yani tüm permütasyonlar değil , tüm kombinasyonlar ) ne kadar hızlı bulabileceğimizden bahseden hiçbir şey bulamadım .N

Bunu biraz düşünüyor ve bana göre zaman ve mekanda çözülebiliyor gibi görünüyor , burada N istenen toplam. Bununla birlikte, konuyla ilgili önceden herhangi bir bilgi bulunmadığından, bunun benim tarafım için önemli bir iddia mı yoksa sadece önemsiz, açık veya zaten bilinen bir sonuç olup olmadığından emin değilim.O(N)N

Öyleyse, soru şu ki, belirli bir için tüm Dört Kare Toplamları ne kadar hızlı bulabiliriz ?N


Tamam, düşündüğüm (neredeyse) O (N) algoritması. İlk iki destek işlevi, en yakın tam sayı karekök işlevi:

    // the nearest integer whose square is less than or equal to N
    public int SquRt(int N)
    {
        return (int)Math.Sqrt((double)N);
    }

Ve 0'dan N'ye kadar toplanan tüm TwoSquare çiftlerini döndüren bir işlev:

    // Returns a list of all sums of two squares less than or equal to N, in order.
    public List<List<int[]>> TwoSquareSumsLessThan(int N)
    {
        //Make the index array
        List<int[]>[] Sum2Sqs = new List<int[]>[N + 1];

        //get the base square root, which is the maximum possible root value
        int baseRt = SquRt(N);

        for (int i = baseRt; i >= 0; i--)
        {
            for (int j = 0; j <= i; j++)
            {
                int sum = (i * i) + (j * j);
                if (sum > N)
                {
                    break;
                }
                else
                {
                    //make the new pair
                    int[] sumPair = { i, j };
                    //get the sumList entry
                    List<int[]> sumLst;
                    if (Sum2Sqs[sum] == null)
                    {   
                        // make it if we need to
                        sumLst = new List<int[]>();
                        Sum2Sqs[sum] = sumLst;
                    }
                    else
                    {
                        sumLst = Sum2Sqs[sum];
                    }
                    // add the pair to the correct list
                    sumLst.Add(sumPair);
                }
            }
        }

        //collapse the index array down to a sequential list
        List<List<int[]>> result = new List<List<int[]>>();
        for (int nn = 0; nn <= N; nn++)
        {
            if (Sum2Sqs[nn] != null) result.Add(Sum2Sqs[nn]);
        }

        return result;
    }

Son olarak, algoritmanın kendisi:

    // Return a list of all integer quads (a,b,c,d), where:
    //      a^2 + b^2 + c^2 + d^2 = N,
    // and  a >= b >= c >= d,
    // and  a,b,c,d >= 0
    public List<int[]> FindAllFourSquares(int N)
    {
        // get all two-square sums <= N, in descending order
        List<List<int[]>> Sqr2s = TwoSquareSumsLessThan(N);

        // Cross the descending list of two-square sums <= N with
        // the same list in ascending order, using a Merge-Match
        // algorithm to find all combinations of pairs of two-square
        // sums that add up to N
        List<int[]> hiList, loList;
        int[] hp, lp;
        int hiSum, loSum;
        List<int[]> results = new List<int[]>();
        int prevHi = -1;
        int prevLo = -1;

        //  Set the Merge sources to the highest and lowest entries in the list
        int hi = Sqr2s.Count - 1;
        int lo = 0;

        //  Merge until done ..
        while (hi >= lo)
        {
            // check to see if the points have moved
            if (hi != prevHi)
            {
                hiList = Sqr2s[hi];
                hp = hiList[0];     // these lists cannot be empty
                hiSum = hp[0] * hp[0] + hp[1] * hp[1];
                prevHi = hi;
            }
            if (lo != prevLo)
            {
                loList = Sqr2s[lo];
                lp = loList[0];     // these lists cannot be empty
                loSum = lp[0] * lp[0] + lp[1] * lp[1];
                prevLo = lo;
            }

            // do the two entries' sums together add up to N?
            if (hiSum + loSum == N)
            {
                // they add up, so cross the two sum-lists over each other
                foreach (int[] hiPair in hiList)
                {
                    foreach (int[] loPair in loList)
                    {
                        // make a new 4-tuple and fill it
                        int[] quad = new int[4];
                        quad[0] = hiPair[0];
                        quad[1] = hiPair[1];
                        quad[2] = loPair[0];
                        quad[3] = loPair[1];

                        // only keep those cases where the tuple is already sorted
                        //(otherwise it's a duplicate entry)
                        if (quad[1] >= quad[2]) //(only need to check this one case, the others are implicit)
                        {
                            results.Add(quad);
                        }
                        //(there's a special case where all values of the 4-tuple are equal
                        // that should be handled to prevent duplicate entries, but I'm
                        // skipping it for now)
                    }
                }
                // both the HI and LO points must be moved after a Match
                hi--;
                lo++;
            }
            else if (hiSum + loSum < N)
            {
                lo++;   // too low, so must increase the LO point
            }
            else    // must be > N
            {
                hi--;   // too high, so must decrease the HI point
            }
        }
        return results;
    }

Daha önce de söylediğim gibi, O (N) 'ye oldukça yakın olmalı, ancak Yuval Filmus'un belirttiği gibi, N'ye Dört Kare çözüm sayısının (N ln ln N) uygun olabileceğinden, bu algoritma olamaz daha az.


Evet, lütfen gönderin. Hala doğrusal algoritma ayrıntılarını geliştiriyorum, ancak geçerli olduğundan eminim.
RBarryYoung

5
Ω(NloglogN)O(N)

1
i=0N/2|hiListNi||loListi|

Evet, bu doğru, ancak formülünüz biraz kapalı çünkü ilk olarak 0 ile apprx arasında değişiyor. N PI / 8 ve ikinci olarak i değerlerinin sadece bir kısmı hiList (Ni) + loList (i) = N'yi tatmin eder, bu yüzden hepsi eklenmez. Her durumda, bunu düzeltmenin bir yolu yoktur ve güzelim bunun mümkün olan en düşük O (N log (log (N))) karmaşıklığını verdiğinden emin olun .
RBarryYoung

Ancak O (n) boşluğunu alan O (max (N, "çözüm sayısı")) içinde çalışan bir algoritmaya sahip olabiliriz.
gnasher729

Yanıtlar:


15

O(N)A,BNM=A2+B2N(A,B)TNMM,NMT

Ω(NloglogN)N8σ(N)σ(N)(eγϵ)NloglogN

N


Hmm, ortadaki buluşma, üzerinde çalıştığım şeye (neredeyse bitti) çok benziyor; bu, TwoSquare çiftleri üzerinde artan / azalan Birleştirme-Eşleştirme algoritması. Kulağa aynı geliyor mu?
RBarryYoung

1
Muhtemelen aynıdır, ortada buluşmak o kadar yaygın bir sezgiseldir ki birçok farklı isme sahip olmalıdır.
Yuval Filmus

σ(N)

σ(N)ο(N)

1
Bölenlerin toplamı gerçekten işlev görür.
Yuval Filmus

5

o(N2)A,B,C,DNO(N2)

O(log2n)O(log2nloglogn)


[1] MO Rabin, JO Shallit, Sayılar Teorisinde Rastgele Algoritmalar , Temel ve Uygulamalı Matematikte İletişim 39 (1986), no. S1, s. S239 – S256 .


Önemsiz bir algoritma için, sadece A, B ve C için döngülere ihtiyacınız var ve sonra D'yi hesaplayın ve bir tamsayı olup olmadığını kontrol edin. A ≤ B ≤ C ≤ D'ye ihtiyacınız varsa O (N ^ 1.5) değerini oldukça küçük bir sabitle almalısınız.
17:12

Yaklaşık 0.04 N ^ 1.5 üçlü (A, B, C) ve N - A ^ 2 - B ^ 2 - C ^ 2'nin kare olup olmadığını kontrol etmek çok hızlı bir şekilde yapılabilir.
gnasher729

-2

8ddn


1
Ve bu soruya nasıl cevap veriyor? Görev, tüm bu dörtlüleri vermektir!
Raphael

1
Bu benim cevabımda zaten belirtilmiş.
Yuval Filmus
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.