Уг бодлогын санаа "Авсаархан Шийдлүүд - 1" бичлэг дээр бичигдчихсэн байв :)
Болхи тоо
(1<=Ni<=10000) гэдгээс F(N) < 2^63 байх юм. (Үүнийг тооцож үзээд шалгачихаж болно) F(K) - нь болхи тоо гэдгээс F(K) * 2, F(K) * 3, F(K) * 5 нь тус тус болхи тоо гэж гарна. Энэ аргаар 2^63-аас бага бүх (~12000 ширхэг) "Болхи тоо"-г урьдчилан тооцоолж олоод эрэмбэлнэ. Ингээд эхний 10000 болхи тоо массивт хадгалаастай байх учраас бодлогын оролтонд харгалзах хариуг амархан гаргаад байж болно.
Анхны тоо шалгагч
Эх хувилбар: Spoj.pl/problems/PON
Анхны тоо шалгадаг магадлалт алгоритмууд болох "Фермагийн магадлалт шалгуур", "Миллер-Рабины магадлалт шалгуур" алинаар нь ч бодож болно. Шалгалтын үр дүнг сайжруулахыг тулд эхний цөөн хэдэн анхны тоог урьдчилан бэлтгэж тэдгээрт хуваагдаж байгаа эсэхийг шалгаж болно. (Эхний 1000 анхны тоо юм уу 10000, 100000 хүртэлх анхны тоонуудад хувааж үзэх)
Програмчлахтай холбоотой асуудал нь:
A^B mod C =-г олох явдал. (1<B, C<2^63)
Bigmod(A, B, C) = A^B mod C гэж тэмдэглэе. Дараах байдлаар програмчилж LogN хугацаанд олж болно
LONG BIGMOD(A, B, C) { if (B mod 2 == 0) { return SQUARE(BIGMOD(A, B/2, C)) mod C } else { return BIGMOD(A, B-1, C) * (A mod C) mod C }}Гэвч ингээд бүрэн бодогдчихгүй юм. Учир нь X*Y mod Z үйлдлийг хийх үед X*Y үйлдлийн хариу нь 2^63 зэрэгтээс халих юм. Иймээс X*Y mod Z үйлдлийг (X+...+X) mod Z (Y удаа нэмнэ) байдлаар шийдэж болно. Үүнийг мөн өмнөх зэрэг дэвшүүлэх үйлдэлтэй адилханаар LogN хугацаанд багтааж болно.MULTIPLY_MOD(X, Y, Z) { if (Y mod 2 == 0) { return MULTIPLY_MOD(X, Y/2, Z) * 2 mod Z } else { return (MULTIPLY_MOD(X, Y-1, Z) + X) mod Z }}MULTIPLY_MOD(X, Y/2, Z) * 2 үйлдэл дээр бас 2^63 -ээс халих асуудал гарах боловч өгөгдлийн төрлөө "UNSIGNED LONG LONG" гэж зааж өгснөөр энэ асуудлыг тойрж болно.Лавлагаа:
[1] Олон оронтой тооноос үлдэгдэл олох хамаагүй сонирхолтой.