N에 해당하는 모든 4 제곱 조합을 얼마나 빨리 찾을 수 있습니까?


12

Stack Overflow ( here ) 에서 질문했습니다 .

정수 주어지면 방정식 A 2 + B 2 + C 2 + D 2 = N 을 해결하는 A , B , CD 의 정수 값의 가능한 모든 조합을 인쇄 하십시오 .NA,B,CDA2+B2+C2+D2=N

이 질문은 물론 수 이론에서 Bachet의 추측 과 관련이 있습니다 (때로는 그의 증거 때문에 Lagrange의 Four Square Theorem이라고도 함). 이 단일 솔루션을 찾는 방법을 논의 할 몇 가지 서류는,하지만 난 아무것도 찾을 수 없었습니다 우리가 찾을 수 있습니다 얼마나 빨리에 대해 이야기 모든 특정 솔루션 (즉, 모든 조합 , 모든 순열 ).N

나는 그것에 대해 꽤 생각하고 있었고 그것은 N 이 원하는 합계 인 시간과 공간 에서 해결할 수 있다고 생각합니다 . 그러나 주제에 대한 사전 정보가 없기 때문에 그것이 그 부분에 대한 중요한 주장인지 또는 사소하거나 명백하거나 이미 알려진 결과인지 확실하지 않습니다.O(N)N

그렇다면 문제는 주어진 대한 4 제곱 합계를 얼마나 빨리 찾을 수 있습니까?N


좋아, 여기 내가 생각했던 (거의) O (N) 알고리즘이 있습니다. 가장 가까운 정수 제곱근 함수 인 처음 두 개의 지원 함수 :

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

그리고 0에서 N까지 합산되는 모든 TwoSquare 쌍을 반환하는 함수 :

    // 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;
    }

마지막으로 알고리즘 자체는 다음과 같습니다.

    // 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;
    }

앞서 말했듯이, Yuval Filmus가 지적한 것처럼 N에 대한 네 개의 제곱 솔루션이 주문 가능하기 때문에 (N ln ln N) O (N)에 매우 가까워 야합니다. 그보다 적습니다.


예, 게시하십시오. 나는 여전히 선형 알고리즘 세부 사항을 개발하고 있지만 그것이 유효한지 확신합니다.
RBarryYoung

5
Ω(NloglogN)O(N)

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

예, 맞습니다.하지만 첫 번째 i의 범위가 0에서 apprx이므로 수식이 약간 벗어났습니다. N PI / 8, 그리고 두 번째로 i 값의 일부만 hiList (Ni) + loList (i) = N을 충족하므로 모두 추가되지는 않습니다. 이것이 O (N log (log (N)))의 가능한 최소한의 복잡성을 제공하는지 확인하십시오 .
RBarryYoung

그러나 O (n) 공간을 차지하면서 O (max (N, "솔루션 수"))로 실행되는 알고리즘을 사용할 수 있습니다.
gnasher729

답변:


15

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

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

N


흠, 중간에서 만나는 것은 내가 작업하고있는 것과 거의 비슷하게 들리는데, 이는 TwoSquare 쌍에서 오름차순 / 내림차순 병합 알고리즘입니다. 그 소리가 똑같습니까?
RBarryYoung

1
아마도 동일하고 중간에 만나는 것은 일반적인 휴리스틱이므로 많은 다른 이름을 가져야합니다.
Yuval Filmus

σ(N)

σ(N)ο(N)

1
제수의 합은 실제로 작동합니다.
Yuval Filmus

5

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

O(log2n)O(log2nloglogn)


[1] MO Rabin, JO Shallit, 수 이론의 무작위 알고리즘 , 순수 및 응용 수학에 관한 커뮤니케이션 39 (1986), no. S1, pp. S239–S256 .


사소한 알고리즘의 경우 A, B 및 C에 대한 루프 만 필요하고 D를 계산하여 정수인지 확인하십시오. A ≤ B ≤ C ≤ D가 필요한 경우 다소 작은 상수로 O (N ^ 1.5)를 얻어야합니다.
gnasher729

약 0.04 N ^ 1.5 트리플 (A, B, C) 및 N-A ^ 2-B ^ 2-C ^ 2가 사각형인지 확인하는 것은 매우 빠르게 수행 될 수 있습니다.
gnasher729

-2

8ddn


1
그리고 이것이 어떻게 질문에 대답합니까? 임무는이 모든 네 배를주는 것입니다!
Raphael

1
이것은 이미 내 대답에 언급되어 있습니다.
Yuval Filmus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.