Нийлмэл тоо бүрийг хамгийн бага анхны хуваагчаар нь яг нэг удаа зурж, анхны тоонуудыг O(n) хугацаанд олдог шигшүүр.
Эхлээд жижиг бодлого
n = 12. Анхны тоонууд нь 2, 3, 5, 7, 11. Нийлмэл тоонуудын хамгийн бага анхны хуваагч: 4, 6, 8, 10, 12-т 2, харин 9-д 3.
Linear Sieve 12-ыг яг нэг удаа, i = 6 үед 6 × 2 гэж зурна. i = 4 үед 4 × 3-ыг зурахгүй, учир нь 3 нь lp[4] = 2-оос их.
Энгийн аргаас санаа руу
Sieve of Eratosthenes анхны тоо бүрийн үржвэрийг зурдаг тул 12-ыг 2-оор ч, 3-аар ч зурна. Нийт ажил нь O(n log log n).
Linear Sieve нийлмэл тоо бүрийг зөвхөн хамгийн бага анхны хуваагчаар нь зурна. x = i × p хэлбэрт p нь lp[i]-гаас их биш байхаар хязгаарлавал p үргэлж x-ийн хамгийн бага анхны хуваагч болно. Ингэснээр тоо бүр нэг л удаа зурагдаж, нийт O(n).
Нэр томьёо ба тэмдэглэгээ
- lp[x]
x-ийн хамгийн бага анхны хуваагч. 0 бол хараахан хэн ч зураагүй.- pr[]
- Олдсон анхны тоонуудын жагсаалт, өсөх дарааллаар.
- cnt
- Олдсон анхны тоонуудын тоо,
pr-ын урт. - i × pr[j]
- Зурж буй тоо.
pr[j] ≤ lp[i]баi × pr[j] ≤ nбайх хооронд л зурна.
lp[x] нь x-ийн хамгийн бага анхны хуваагч. 2-оос 30 хүртэлх бүх тоонд lp бөглөнө. Гол санаа: нийлмэл тоо бүрийг яг нэг удаа, өөрийнх нь хамгийн бага анхны хуваагчаар зурна.
- Space тоглуулах
- ←→ алхам
- −+ хурд
- Одоогийн i
- Сая зурсан
- Нийлмэл тоо
- Анхны тоо
- Олдсон анхны тоо
Илүү ухаалаг шигшүүр
Sieve of Eratosthenes 12-ыг 2 удаа зурдаг: 2-оор ч, 3-аар ч. Linear Sieve нийлмэл тоо бүрийг яг нэг удаа зурна. Мөн lp[x] буюу x-ийн хамгийн бага анхны хуваагчийг олно.
Дараа нь юу болох вэ?
Оноо 0 / 00дараалсан зөв, хамгийн их 0
Animation нэг алхам дээр зогсоно. Дараа нь код юу хийх вэ? Таагаад оноо цуглуул! Нэвтрэх хэрэггүй, оноо чинь энэ төхөөрөмж дээр хадгалагдана.
Юунд хэрэгтэй вэ?
n хүртэлх бүх анхны тоо, мөн тоо бүрийн хамгийн бага анхны хуваагч lp[x]-ийг олно. lp ашиглан дурын тоог хурдан задална.
Яаж ажилладаг вэ?
1. i = 2 … n. lp[i] хоосон бол i анхны тоо: lp[i] = i болгоод pr жагсаалтад нэмнэ. 2. pr доторх анхны тоо p бүрийн хувьд lp[i × p] = p гэж бичнэ. 3. p > lp[i] эсвэл i × p > n болмогц зогсоно. 4. Ингэснээр нийлмэл тоо бүр өөрийн хамгийн бага анхны хуваагчаар нэг л удаа зурагдана. Оролт: n. Анхны тоонуудыг хэвлэнэ.
Яагаад зөв, хэр хурдан бэ?
Нийлмэл x-ийн хамгийн бага анхны хуваагчийг p гэе. x = i × p бол i-н бүх анхны хуваагч p-гээс багагүй, тиймээс p ≤ lp[i]. Тэгэхээр i дээр ирэхэд x заавал зурагдана. Өөр p' хуваагчаар x-ийг зурах гэвэл p' > lp[i'] нөхцөл зөрчигдөнө. Иймд тоо бүр яг нэг удаа зурагдана.
Нийт зурах үйлдлийн тоо нь нийлмэл тоонуудын тоотой тэнцүү, тиймээс O(n). n = 10⁷ бол 10 сая орчим үйлдэл. Санах ой: lp array n + 1 хэмжээтэй.
Түгээмэл алдаа
pr[j] <= lp[i]нөхцөлийг мартах. Тэгвэл тоо олон удаа зурагдаж,lpбуруу утгатай болно.i * pr[j]int-ээс хэтрэх. n ойролцоогоор 10⁷ бол асуудалгүй, гэхдээ шалгалтыгi * pr[j] <= nгэж үржвэрээр хийдэг тул n том болlong longхэрэглэ.lparray-г n-ээс бага зарлах. Index n хүртэл хэрэгтэй тулn + 1.
Хязгаарын тохиолдол
- n = 2: ганц анхны тоо 2 олдоно, зурах тоо алга.
- Анхны тоо
iдээр:lp[i] = iтулprдоторх бүх анхны тоогоор (n-ээс хэтрэхгүй бол) үржүүлнэ. - n = 30-аас 60 болгоход шинэ анхны тоонууд нэмэгдэх ч өмнөх
lpутгууд өөрчлөгдөхгүй.
Өөрийгөө шалга
lp[45]хэд вэ? 45-ыг альiүед зурах вэ?Хариу харах
lp[45] = 3. i = 15 үед15 × 3гэж зурна, учир ньlp[15] = 3.n = 30 бол нийт хэдэн удаа зурах вэ?
Хариу харах
19. 2-оос 30 хүртэл 29 тоо, үүнээс 10 нь анхны, 19 нь нийлмэл.
Гурван дадлага
Hint-ээ нээхээс өмнө өөрөө оролдоорой.
1.n = 20 бол 2-оос 20 хүртэлх нийлмэл тоо бүрийн
lpутгыг бич.Hint харах
Зөвхөн 9 ба 15-ын
lpнь 2 биш.Хариу ба тайлбар
4, 6, 8, 10, 12, 14, 16, 18, 20-т 2. 9 ба 15-д 3.
2.
lparray ашиглан дурынx ≤ n-ийг анхны үржвэрт задалдаг код бич.Hint харах
lp[x]нь үргэлж анхны хуваагч.Хариу ба тайлбар
while (x > 1) { cout << lp[x] << " "; x /= lp[x]; }Алхмын тоо нь хүчин зүйлсийн тоо, O(log x). 360 дээр2 2 2 3 3 5.3.Linear Sieve-ийн зэрэгцээ 1-ээс n хүртэлх бүх тооны φ-г ол.
Hint харах
p = lp[i]үедφ(i × p) = φ(i) × p. Бусад үедφ(i × p) = φ(i) × (p − 1).Хариу ба тайлбар
Анхны
i-дphi[i] = i - 1. Зурах бүрт дээрх хоёр томьёоны аль тохирохыг нь хэрэглэнэ. Нийт O(n) хэвээр.
Жишээ
Оролт
30
Гаралт
2 3 5 7 11 13 17 19 23 29