ไม่ใช่ตัวหารสามัญน้อยที่สุด


11

โดยทั่วไปปัญหาคือ: สำหรับชุดของตัวเลขบวกพบจำนวนน้อยที่สุดที่ไม่ได้เป็นตัวหารขององค์ประกอบของคือxSdSxS, dx

แสดงว่าn=|S|และC=max(S)(S) พิจารณาฟังก์ชันF(x)=จำนวนที่สำคัญอย่างน้อยไม่หารxxมันเป็นเรื่องง่ายที่จะเห็นว่าF(x)logxx และสำหรับชุดSให้F(S)=นายกอย่างน้อยที่ไม่ได้แบ่งองค์ประกอบของSSเรามีขอบเขตบน

F(S)F(lcm(S))F(Cn)nlogC.

ดังนั้นขั้นตอนวิธีการแรงเดรัจฉานง่ายซึ่งระบุตัวเลขทั้งหมดจาก1ไปnlogCและการตรวจสอบถ้ามันไม่ได้แบ่งองค์ประกอบของSเป็นพหุนามและมีเวลาซับซ้อนO(n2logC)C)

วิธีอื่น ๆ ในการแก้ปัญหาคือการคำนวณปัจจัยทั้งหมดสำหรับองค์ประกอบของทุกSและใช้พวกเขาในอัลกอริทึมแรงเดรัจฉานเพื่อตรวจสอบว่าxเป็นคำตอบในO(1)เวลา อัลกอริทึมนี้มีความซับซ้อนของเวลาO(nmin(C,nlogC)+nlogC)และใช้หน่วยความจำO(nlogC)เพราะเราไม่จำเป็นต้องคำนวณและ ปัจจัยที่ร้านมากกว่าnlogCC สำหรับnและCขนาดเล็กCมันทำงานได้ดีขึ้น

รายละเอียดอัลกอริทึมประกอบด้วยสองส่วน:

  1. สร้างชุดS^ประกอบด้วยปัจจัยทั้งหมดขององค์ประกอบทั้งหมดของS , คือ

    xS fnlogC, (fxfS^)
    สามารถทำได้ในเวลาO(nmin(C,nlogC))เวลาและหน่วยความจำO(nlogC)(สิ่งนี้มาจากที่ใดสำหรับองค์ประกอบใด ๆ ของSเราสามารถแยกปัจจัยโดยใช้การแยกตัวประกอบของการทดลองกับตัวเลขทั้งหมดจนถึงCหรือจำนวนเฉพาะทั้งหมดถึงnlogCแล้วแต่จำนวนใดจะน้อยกว่าดังนั้นองค์ประกอบของSแต่ละตัวSสามารถแยกตัวประกอบในเวลาO(min(C,nlogC)) )
  2. พบจำนวนน้อยที่สุด{S} ขั้นตอนนี้ต้องใช้เวลาถ้าตรวจสอบว่าสามารถทำได้ในเวลาdS^O(|S^|)=O(nlogC)xS^O(1)

ฉันมีสองคำถามที่ฉันสนใจ:

  1. มีอัลกอริทึมที่เร็วกว่านี้ในการแก้ปัญหาหรือไม่
  2. สำหรับและได้รับเราจะสร้างชุดมีตัวหารไม่ธรรมดาน้อยที่สุดได้อย่างไรnCS

1. โดย "precompute" ฉันหมายถึงก่อนที่จะเริ่มอัลกอริทึมแรงเดรัจฉาน 2. ความซับซ้อนของแฟคือ subexponential แน่นอนดู Definiton ของCC
SkyterX

@DW ในจุดที่ 2 ความซับซ้อนของแฟคตอริ่งนั้นอยู่ที่ความยาวของบิตสตริแทนจำนวน แต่ SkyterX อย่างถูกต้องบอกว่ามันเป็นนั่นคือสัดส่วนกับรากที่สองของขนาดของ จำนวน. O(C)
Lieuwe Vinkhuijzen

@LieuweVinkhuijzen นั่นดูไม่เหมาะกับฉัน ความซับซ้อนของแฟ็กเตอริ่งโดยใช้ GNFS จะเหมือนกับซึ่งน้อยกว่าอย่างมาก{C}) ดูen.wikipedia.org/wiki/… . O(exp{1.9(logC)1/3(loglogC)2/3})O(C)
DW

คำสั่งที่วิธีที่สองทำงานได้ดีขึ้น "สำหรับขนาดเล็กและ " ไม่ถูกต้อง มันทำงานได้ดีกว่า แต่ถ้า(C) ดังนั้นต้องมีขนาดใหญ่สำหรับวิธีที่สองเพื่อประสิทธิภาพที่ดีขึ้น (ไม่เล็ก) nCnC/log(C)n
DW

@DW ถูกต้องฉันไม่ทราบถึงความซับซ้อนของ GNFS
Lieuwe Vinkhuijzen

คำตอบ:


6

เป็นไปได้ที่จะปรับปรุงอัลกอริทึมที่สองของคุณโดยใช้อัลกอริธึมที่ดีกว่าสำหรับการแยกตัวประกอบจำนวนเต็ม

มีสองอัลกอริทึมสำหรับการแยกตัวประกอบจำนวนเต็มที่เกี่ยวข้องที่นี่:

  • GNFSสามารถปัจจัยจำนวนเต็มกับการทำงานเวลา[0.33,1.92])CO(LC[0.33,1.92])

  • ECMสามารถค้นหาปัจจัย (ถ้ามี) ด้วยเวลาทำงาน ; การค้นหาปัจจัยทั้งหมดจะใช้เวลานานเท่า (ซึ่งค่อนข้างเล็กเมื่อเทียบกับเวลาทำงานของ ECM)nlogCO(LnlogC[0.5,1.41])O(logC/log(nlogC))

นี่\}Ln[α,c]=exp{c(logn)α(loglogn)1α}

นั่นเป็นนิพจน์ที่ดูน่ากลัวสำหรับเวลาทำงาน แต่ความจริงที่สำคัญคือมันเร็วกว่าวิธีที่คุณพูดถึง โดยเฉพาะอย่างยิ่งเป็น asymptotically มีขนาดเล็กกว่าคือ GNFS เร็วกว่าพยายามปัจจัยเป็นไปได้ทั้งหมด{C} นอกจากนี้ยังเป็น asymptotically มีขนาดเล็กกว่าคือ ECM จะเร็วกว่าพยายามปัจจัยเป็นไปได้ทั้งหมดCLC[0.33,1.92]CCLnlogC[0.5,1.41]nlogCnlogC

ดังนั้นเวลาทำงานทั้งหมดของวิธีนี้คือและนี่คือ asymptotically ดีกว่าของคุณ วิธีแรกและ asymptotically ดีกว่าวิธีที่สองของคุณ ฉันไม่รู้ว่าเป็นไปได้ไหมที่จะทำสิ่งที่ดีกว่านี้O~(nmin(LC[0.33,1.92],LnlogC[0.5,1.41]))


ฉันเดาว่าอัลกอริธึมที่รวดเร็วสำหรับปัญหานี้จะต้องมีการแยกตัวประกอบชุดอินพุตบางอย่าง ฉันจะตรวจสอบอัลกอริทึมการแยกตัวประกอบเหล่านั้น แต่ยังคงมีปัญหาในการทดสอบอย่างถูกต้องซึ่งเพิ่มปัญหาที่สองที่ฉันกล่าวถึงการสร้างชุดด้วยคำตอบสูงสุด SS
SkyterX

ECM ค้นหาปัจจัยหนึ่งในเวลาที่คุณให้ หากปัจจัยทั้งหมดของตัวเลขเป็น logn log C คุณจะต้องทำซ้ำอัลกอริทึมซ้ำจนถึงล็อก C / log (n log C) ครั้ง
gnasher729

3

non-divisor ที่น้อยที่สุดอาจมีขนาดใหญ่เท่ากับ N log C แต่ถ้าจำนวน N กระจายแบบสุ่มแล้ว non-divisor ทั่วไปที่น้อยที่สุดน่าจะเล็กกว่ามากอาจน้อยกว่า N มากฉันจะสร้างตารางที่ ช่วงเวลาเป็นตัวหารของตัวเลข

สำหรับแต่ละหมายเลขเฉพาะ p เรามีดัชนีซึ่งหมายความว่าตัวเลขทั้งหมดจนถึงดัชนีนั้นได้รับการตรวจสอบการหารด้วย p และเรามีรายการตัวเลขทั้งหมดที่หารด้วยkp

จากนั้นสำหรับ d = 2, 3, 4, ... เราพยายามหาตัวเลขหารด้วย d หรือแสดงว่าไม่มี เราใช้ค่าตัวประกอบเฉพาะ p ที่ใหญ่ที่สุดของ d จากนั้นเราตรวจสอบตัวเลขทั้งหมดที่หารด้วย p ไม่ว่าพวกมันหารด้วย d หรือไม่ หากไม่พบเราจะตรวจสอบตัวเลขเพิ่มเติมด้วยดัชนี>สำหรับการหารด้วย p อัปเดตและรายการตัวเลขที่หารด้วย p และตรวจสอบว่าแต่ละตัวเลขหารด้วย d หรือไม่kpkp

ในการตรวจสอบว่ามีตัวเลขหารด้วย p หรือไม่เราจะตรวจสอบหมายเลข p โดยเฉลี่ย ในภายหลังหากเราตรวจสอบว่ามีตัวเลขหารด้วย 2p มีโอกาส 50% ที่เราต้องตรวจสอบเพียงหมายเลขเดียว (ตัวเลขที่หารด้วย p) และมีโอกาส 50% สำหรับการตรวจสอบโดยเฉลี่ยอีก 2p การหาจำนวนที่หารด้วย 3p นั้นค่อนข้างเร็วและต่อไปและเราไม่เคยตรวจสอบตัวเลข N มากกว่าสำหรับการหารด้วย p เพราะมีเพียงตัวเลข N เท่านั้น

ฉันหวังว่าสิ่งนี้จะได้ผลโดยใช้การตรวจสอบการแบ่งแยกเกี่ยวกับN2/logN

PS ผลลัพธ์จะมีขนาดใหญ่เท่าใดสำหรับตัวเลขสุ่ม

สมมติว่าฉันมีตัวเลขสุ่ม N ตัว ความน่าจะเป็นที่ตัวเลข N ตัวใดตัวหนึ่งหารด้วย d ได้คือ 1 - (1 - 1 / d) ^ N ฉันถือว่าความน่าจะเป็นที่ตัวเลขแต่ละตัว 1 ≤ d ≤ k เป็นปัจจัยหนึ่งของตัวเลขสุ่มที่คำนวณโดยการคูณความน่าจะเป็นเหล่านี้ (โอเคนั่นเป็นบิตที่ค่อนข้างหลบเพราะความน่าจะเป็นเหล่านี้ไม่ค่อยอิสระ

ด้วยสมมติฐานดังกล่าวด้วย N = 1,000 มีโอกาส 50% ที่หนึ่งในตัวเลข 1..244 ไม่ได้หารตัวเลขใด ๆ และหนึ่งในพันล้านที่ทุก ๆ ตัวเลขที่มากถึง 507 จะหารตัวเลขหนึ่งตัว ด้วย N = 10,000 มีโอกาส 50% ที่หนึ่งในตัวเลข 1..1726 ไม่ได้หารตัวเลขใด ๆ และหนึ่งในพันล้านที่ทุก ๆ ตัวเลขที่มากถึง 2979 หารตัวเลขหนึ่งตัว

ฉันจะเสนอว่าสำหรับอินพุตแบบสุ่มของ N ขนาดของผลลัพธ์นั้นใหญ่กว่า N / ln N เล็กน้อย อาจจะเป็นอะไรที่เหมือน N / ln N * (ln ln N) ^ 2 นี่คือเหตุผล:

น่าจะเป็นที่อย่างน้อยหนึ่งของตัวเลขสุ่ม N คือหารด้วยสุ่ม d เป็น N ถ้า d มีค่าประมาณ N ดังนั้นจะมีค่าประมาณ 1 - exp (-1) ≈ 0.6321 สำหรับตัวหารเดียว โอกาสที่แต่ละหมายเลขหลายตัว d d N เป็นตัวหารอย่างน้อยหนึ่งหมายเลข N นั้นค่อนข้างผอมดังนั้นค่า d สูงสุดจะเล็กกว่า N อย่างมาก1(11/d)N1(11/d)N

หาก d << N แล้วD)1(11/d)N1exp(N/d)

หาก d ≈ N / LN N แล้วกด N1exp(N/d)1exp(lnN)=11/N

เราจะเพิ่มความน่าจะเป็นเหล่านี้สำหรับค่า N / ln N แต่สำหรับ d ส่วนใหญ่ผลลัพธ์จะใหญ่ขึ้นอย่างมีนัยสำคัญดังนั้นค่า d ที่ใหญ่ที่สุดจะมีขนาดใหญ่กว่า N / ln N อย่างใดอย่างหนึ่ง แต่เล็กกว่า N อย่างมาก

PS การหาจำนวนหารด้วย d:

เราเลือกไพร์มแฟคเตอร์ p ที่ใหญ่ที่สุดจากนั้นเราตรวจสอบตัวเลขที่รู้กันแล้วว่าหารด้วย p พูด d = kp จากนั้นโดยเฉลี่ยเราจะตรวจสอบตัวเลข k ที่หารด้วย p ในขณะที่ตรวจสอบ d นี้โดยเฉพาะและเราตรวจสอบค่า N ทั้งหมดสำหรับการหารด้วย p โดยรวมแล้วสำหรับทั้งหมด d หารด้วย p ที่จริงแล้วเราน่าจะตรวจสอบน้อยกว่าค่า N สำหรับช่วงเวลาส่วนใหญ่ p เพราะหลังจากการตรวจสอบค่า N ทั้งหมดอัลกอริทึมที่น่าจะสิ้นสุด ดังนั้นหากผลลัพธ์คือ R ดังนั้นฉันคาดว่าค่า N น้อยกว่าจะถูกหารด้วยนายกแต่ละตัวน้อยกว่า R สมมติว่า R ≤ N นั่นคือประมาณ N ^ 2 / log N การตรวจสอบ

PS ใช้การทดสอบบางอย่าง

ฉันใช้อัลกอริธึมนี้สองสามครั้งโดยมีตัวเลขสุ่ม = N = 1,000,000> 0 ตัวหารที่ไม่ธรรมดาที่พบน้อยที่สุดคือระหว่าง 68,000 ถึง 128,000 โดยที่ส่วนใหญ่วิ่งระหว่าง 100,000 ถึง 120,000 จำนวนแผนกอยู่ระหว่าง 520 ล้านถึง 1,800 ล้านซึ่งน้อยกว่า (N / ln N) ^ 2; กรณีส่วนใหญ่ใช้ระหว่าง 1,000 ถึง 1,500 ล้านดิวิชั่น

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