เราสามารถหาชุดค่าผสม Four-Square ทั้งหมดที่รวมกับ N ได้อย่างรวดเร็วแค่ไหน


12

มีคำถามที่ Stack Overflow ( ที่นี่ ):

ได้รับจำนวนเต็ม , พิมพ์ออกมารวมกันเป็นไปได้ทั้งหมดของค่าจำนวนเต็มของและซึ่งการแก้สมการNA , B , C D A 2 + B 2 + C 2 + D 2 = NNA,B,CDA2+B2+C2+D2=N

คำถามนี้แน่นอนว่าเกี่ยวข้องกับทฤษฎีการคาดเดาของ Bachetในทฤษฎีจำนวน (บางครั้งเรียกว่าทฤษฎีบท Four Square ของ Lagrange เพราะหลักฐานของเขา) มีเอกสารบางฉบับที่พูดถึงวิธีการหาทางออกเดียว แต่ฉันไม่สามารถหาอะไรที่พูดถึงความเร็วที่เราสามารถหาวิธีแก้ปัญหาทั้งหมดสำหรับเฉพาะเจาะจง(นั่นคือการรวมกันทั้งหมดไม่ใช่การเปลี่ยนลำดับทั้งหมด)N

ฉันคิดอยู่นิดหน่อยและดูเหมือนว่าฉันสามารถแก้ไขได้ในเวลาและสถานที่โดยที่คือผลรวมที่ต้องการ อย่างไรก็ตามหากขาดข้อมูลก่อนหน้านี้ในเรื่องนี้ฉันไม่แน่ใจว่านี่เป็นข้อเรียกร้องที่มีนัยสำคัญในส่วนของฉันหรือเพียงแค่ผลลัพธ์เล็กน้อยที่เห็นได้ชัดหรือเป็นที่รู้จักแล้วNO(N)N

ดังนั้นคำถามก็คือเราจะหาผลบวกสี่สแควร์ทั้งหมดสำหรับกำหนดได้เร็วแค่ไหน?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);
    }

และฟังก์ชั่นเพื่อส่งคืนคู่ TwoSquare ทั้งหมดที่รวมจาก 0 ถึง N:

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

อย่างที่ฉันพูดไว้ก่อนหน้านี้มันควรจะค่อนข้างใกล้เคียงกับ O (N) อย่างไรก็ตามในขณะที่ Yuval Filmus ชี้ให้เห็นเนื่องจากจำนวนโซลูชั่นสี่สแควร์ถึง N สามารถเป็นระเบียบได้ (N ln ln N) ดังนั้นอัลกอริทึมนี้ไม่สามารถ น้อยกว่านั้น


ใช่กรุณาโพสต์ ฉันยังคงพัฒนารายละเอียดอัลกอริทึมเชิงเส้น แต่ฉันค่อนข้างมั่นใจว่ามันถูกต้อง
RBarryYoung

5
สำหรับเร็กคอร์ดปรากฏว่าบางครั้งมีโซลูชันมากที่สุดเท่าที่ดังนั้นเราจึงไม่มีอัลกอริทึมΩ(NloglogN)O(N)
Yuval Filmus

1
จากที่นี่ดูเหมือนว่า catch (และปัจจัยที่ไม่ใช่เชิงเส้นพิเศษ) มาจาก foreach () สองวงที่อยู่ภายใน main ของคุณขณะที่ loop เวลาทั้งหมดของคุณคือและปัญหาคือขนาดของ hiList และ loList ไม่จำเป็นต้องมีค่าคงที่ใด ๆ i=0N/2|hiListNi||loListi|
Steven Stadnicki

ใช่มันถูกต้องแล้ว แต่สูตรของคุณออกไปเล็กน้อยเพราะครั้งแรกที่ฉันมีตั้งแต่ 0 ถึง apprx N PI / 8 และที่สองมีเพียงเศษเสี้ยวของ i ที่ตอบสนอง hiList (Ni) + loList (i) = N ดังนั้นพวกเขาจึงไม่ได้ถูกเพิ่มเข้ามาในทุกกรณีไม่ว่าจะมีวิธีใดในการแก้ไขปัญหานี้และฉันก็สวย แน่ใจว่าสิ่งนี้ให้ความซับซ้อนน้อยที่สุดที่เป็นไปได้ของ O (N log (log (N))
RBarryYoung

แต่เราสามารถมีอัลกอริทึมที่ทำงานใน O (สูงสุด (N, "จำนวนโซลูชั่น")) โดยใช้พื้นที่ O (n)
gnasher729

คำตอบ:


15

อัลกอริทึมของ Juho สามารถปรับปรุงเป็นอัลกอริทึมโดยใช้การประชุมตรงกลาง ไปทุกคู่ ; สำหรับแต่ละคู่ที่ , เก็บในอาร์เรย์ของความยาว (แต่ละตำแหน่งอาจมีหลายคู่ซึ่งอาจถูกเก็บไว้ในรายการที่เชื่อมโยง) ตอนนี้ไปที่คู่ซึ่งเซลล์ที่เกี่ยวข้องในนั้นจะไม่ว่างเปล่าO(N) M=A2+B2N(A,B)TNMM,N-MTA,BNM=A2+B2N(A,B)TNMM,NMT

วิธีนี้เราจะได้การแทนค่าโดยรวมของ quadruples ทั้งหมด ถ้าเราต้องการแสดงรายการทั้งหมดของพวกเราเราก็ไม่สามารถทำได้ดีกว่าเนื่องจากทฤษฎีบทสี่ตารางของ Jacobiแสดงให้เห็นว่า (สำหรับคี่ ) จำนวนการแทนคือและมีจำนวนเต็มมากมายเช่น (ดูทฤษฎีบทของGrönwall )N 8 σ ( N ) σ ( N ) ( e γ - ϵ ) N บันทึกล็อกNΩ(NloglogN)N8σ(N)σ(N)(eγϵ)NloglogN

เพื่อให้ได้อัลกอริธึมที่น้อยกว่าเราสามารถลองใช้ปัจจัยกับวงแหวน quaternion ที่เหมาะสมเนื่องจากเรารู้ว่าการแทนเป็นผลบวกของสี่เหลี่ยมสองช่องนั้นสอดคล้องกัน เรายังคงต้องหาตัวแทนที่เกี่ยวข้องทั้งหมดN


อืมสิ่งที่พบตรงกลางนั้นคล้ายกับสิ่งที่ฉันกำลังทำอยู่ (เกือบเสร็จแล้ว) ซึ่งเป็นอัลกอริทึม Merge-Match จากน้อยไปมาก / มากไปหาน้อยในคู่ TwoSquare เสียงนั้นเหมือนกันหรือไม่
RBarryYoung

1
มันอาจจะเหมือนกันการพบปะกันในตอนกลางนั้นเป็นวิธีแก้ปัญหาร่วมกันที่ต้องมีชื่อแตกต่างกันมากมาย
Yuval Filmus

อืมฉันออกจากสถาบันการศึกษามาสามสิบปีแล้วอะไรคือสิ่งที่หมายถึงอะไร (หรือคุณสามารถชี้ให้ฉันอ้างอิงได้) ขอบคุณ σ(N)
RBarryYoung

หรือเป็นที่จริงๆ ? ο ( N )σ(N)ο(N)
RBarryYoung

1
ผลรวมของตัวหารทำงานแน่นอน
Yuval Filmus

5

ฉันคิดว่าอัลกอริธึมเวลาไม่ใช่สิ่งเล็กน้อยและต้องการความเข้าใจบางอย่างหากมีอยู่ อัลกอริทึมที่เห็นได้ชัดที่ทำงานในเวลากำลังสองระบุ tuplesทั้งหมด ซึ่งสามารถทำได้ในสี่ลูปเพื่อความซับซ้อนของเวลาทั้งหมดที่จะกลายเป็น2) นอกจากนี้ยังระบุโซลูชั่นทั้งหมดอย่างชัดเจน, B , C , D o(N2) O(N2)A,B,C,DNO(N2)

อัลกอริธึมที่เกี่ยวข้อง Rabin และ Shallit [1] นำเสนออัลกอริธึมแบบสุ่มสองแบบสำหรับการแยกย่อยจำนวนเต็มเป็นผลรวมของกำลังสอง สำหรับสองกำลังสองพวกมันให้อัลกอริทึมเวลาที่คาดหวังสำหรับสี่สี่เหลี่ยมพวกเขาให้อัลกอริทึมเวลาที่คาดหวังโปรดทราบว่าอัลกอริทึมไม่ได้ให้โซลูชันทั้งหมดแก่คุณแต่มีเพียงโซลูชันเดียวO ( บันทึก2 n บันทึกบันทึกn )O(log2n)O(log2nloglogn)


[1] MO Rabin, JO Shallit, อัลกอริทึมแบบสุ่มในทฤษฎีจำนวน , การสื่อสารเกี่ยวกับคณิตศาสตร์บริสุทธิ์และประยุกต์ 39 (1986), ไม่ 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

จำนวนการแก้ปัญหาคือโดยที่ไปหาร div ทั้งหมดของซึ่งไม่ใช่ทวีคูณของ 4 นี่คือทฤษฎีบทของ Jacobid n8ddn


1
และนี่จะตอบคำถามอย่างไร ภารกิจคือให้สี่เท่าทั้งหมดนี้!
Raphael

1
นี่ถูกกล่าวถึงแล้วในคำตอบของฉัน
Yuval Filmus
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.