|
Serwis Edukacyjny w I-LO w Tarnowie
Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej
Autor artykułu: mgr Jerzy Wałaszek |
©2026 mgr Jerzy Wałaszek
|
ProblemZnaleźć rozkład liczby p > 1 na iloczyn czynników pierwszych. Pierre de Fermat podał prosty sposób znajdowania czynników (liczb dzielących p bez reszty) liczby nieparzystej p. Opiera się on na spostrzeżeniu, iż jeśli potrafimy znaleźć dwie liczby naturalne x i y, takie że: p = x2-y2 to p = (x+y)×(x-y) zatem czynnikami liczby p są: m = x+y n = x-y Znalezione czynniki m i n nie muszą być liczbami pierwszymi, zatem metodę Fermata stosujemy również do ich rozkładu. Jest to możliwe, ponieważ czynniki liczby nieparzystej są również nieparzyste. Czynniki o wartości 2 można wyeliminować z p przed zastosowaniem metody Fermata, zatem nie jest to żadne ograniczenie. Metoda Fermata jest szczególnie efektywna w przypadku czynników leżących w pobliżu pierwiastka z p. W przeciwnym razie jej efektywność jest taka sama lub nawet gorsza jak dla metody próbnych dzieleń. W praktyce metoda Fermata nie jest używana –podajemy ją ze względów dydaktycznych oraz z powodu jej wagi dla innych, bardziej zaawansowanych metod poszukiwań rozkładu liczby na czynniki pierwsze. |
Algorytm wykorzystuje bezpośrednio własność
y2 = x2-p
Następnie sprawdzamy, czy y jest liczbą całkowitą. Jeśli tak, to
znaleźliśmy odpowiednie liczby x i y. Ponieważ liczba
p
z założenia jest nieparzysta, to wszystkie jej dzielniki są nieparzyste.
Obliczamy dzielniki
Ponieważ czynnik musi być mniejszy lub równy p, to:
m = x+y ≤ p
Przy wzroście x rośnie również y lub pozostaje takie samo. Zatem gdy suma x+y przekroczy p, to nie znajdziemy już żadnego dzielnika liczby p i algorytm można zakończyć przyjmując, iż p jest pierwsze.
K01: x ← ceil(sqr(p)) ; obliczamy wartość początkową dla x K02: z ← x2-p ; z = y2 K03: y ← ceil(sqr(z)) ; sprawdzamy, czy z jest kwadratem liczby naturalnej K04: Jeśli z ≠ y2, to idź do kroku K11 K05: m ← x+y ; obliczamy czynniki K06: n ← x-y K07: Jeśli n = 1, ; przerywamy przy n = 1, gdyż p jest pierwsze to idź do kroku K13 K08: Fermat(m) ; rozkładamy rekurencyjnie czynniki m i n K09: Fermat(n) K10: Zakończ K11: x ← x+1 ; następne x K12: Jeśli x+y < p, ; kontynuujemy pętlę to idź do kroku K02 K13: Pisz p ; p jest pierwsze K14: Zakończ
|
Uwaga: Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
| Program w pierwszym wierszu czyta dowolną liczbę naturalną p > 1 i w następnym wierszu wypisuje kolejne czynniki pierwsze tej liczby. Czynniki mogą nie być wypisywane w kolejności rosnącej. Zwróć uwagę, iż do poprawnego działania zmienna x musi być zadeklarowana jako 64 bitowa – w przeciwnym razie dla dużych liczb jej kwadrat wyjdzie poza zakres liczb 32-bitowych. W efekcie program może dokonywać rozkładu na czynniki pierwsze liczb 32 bitowych. |
Pascal// Metoda Fermata
// Data: 27.03.2008
// (C)2020 mgr Jerzy Wałaszek
//---------------------------
program prg;
uses math;
procedure Fermat(p : longword);
var x, y, z, m, n : qword;
begin
x := ceil(sqrt(p));
repeat
z := x*x-p;
y := floor(sqrt(z));
if z = y*y then
begin
m := x+y;
n := x-y;
if n = 1 then break;
Fermat(m);
Fermat(n);
exit;
end;
inc(x);
until x+y >= p;
write(p, ' ');
end;
var p : longword;
begin
readln(p);
while p mod 2 = 0 do
begin
p := p div 2;
write(2, ' ');
end;
if p > 1 then
Fermat(p);
writeln;
end. |
// Metoda Fermata
// Data: 27.03.2008
// (C)2020 mgr Jerzy Wałaszek
//---------------------------
#include <iostream>
#include <cmath>
using namespace std;
void Fermat(unsigned int p)
{
unsigned long long x, y, z, m, n;
x = (unsigned long long)ceil(sqrt(p));
do
{
z = x*x-p;
y = (unsigned long long)floor(sqrt(z));
if(z == y*y)
{
m = x+y;
n = x-y;
if(n == 1) break;
Fermat(m);
Fermat(n);
return;
}
x++;
} while(x+y < p);
cout << p << " ";
}
int main()
{
unsigned int p;
cin >> p;
while(p % 2 == 0)
{
p /= 2;
cout << 2 << " ";
}
if(p > 1) Fermat(p);
cout << endl;
return 0;
} |
Basic' Metoda Fermata
' Data: 27.03.2008
' (C)2020 mgr Jerzy Wałaszek
'----------------------------
Sub Fermat(Byval p As Uinteger)
Dim As Ulongint x, y, z, m, n
x = Ceil(Sqr(p))
Do
z = x*x-p
y = Floor(Sqr(z))
If z = y*y Then
m = x+y
n = x-y
If n = 1 Then Exit Do
Fermat(m)
Fermat(n)
Exit Sub
End If
x += 1
Loop Until x+y >= p
Print p;" ";
End Sub
Function Ceil(Byval x As Double) _
As Ulongint
Dim result As Ulongint
result = Culngint(x)
If result < x Then _
result += 1
Ceil = result
End Function
Function Floor(Byval x As Double) _
As Ulongint
Dim result As Ulongint
result = Culngint(x)
If result > x Then _
result -= 1
Floor = result
End Function
Dim p As Uinteger
Input p
while p mod 2 = 0
p = p shr 1
print 2;" ";
wend
if p > 1 then _
Fermat(p)
Print
End |
Python (dodatek)# Metoda Fermata
# Data: 12.02.2024
# (C)2024 mgr Jerzy Wałaszek
# --------------------------
import math
def fermat(p):
x = math.ceil(math.sqrt(p))
while 1:
z = x*x-p
y = math.floor(math.sqrt(z))
if z == y*y:
m = x+y
n = x-y
if n == 1: break
fermat(m)
fermat(n)
return
x += 1
if x+y >= p: break
print(p, end=" ")
return
p = int(input())
while not (p % 2):
p >>= 1
print(2, end=" ")
if p > 1: fermat(p)
print()
|
| Wynik: |
855855 11 7 13 3 3 5 19 |
Podstawową wadą pierwszego rozwiązania jest konieczność wyznaczania wartości pierwiastka kwadratowego. Niestety, jest to operacja dosyć czasochłonna. Zastanówmy się zatem, czy algorytmu Fermata nie można zapisać w inny sposób, tak aby nie było konieczności wyznaczania pierwiastków kwadratowych w pętli poszukującej dzielników. Dokonajmy najpierw kilku prostych spostrzeżeń.
Jeśli mamy daną wartość kwadratu liczby naturalnej, np. x2, to kwadrat następnej liczby x+1 można wyznaczyć następująco:
(x+1)2 = x2+2x+1 = x2+dx; gdzie: dx = 2x+1
Ponieważ x wzrosło o 1, to nowy przyrost dx' wyniesie:
dx' = 2(x+1)+1 = 2x+2+1 = (2x+1)+2 = dx+2
Wynika stąd, iż mając wartość początkową kwadratu x2 oraz dx, kolejne kwadraty obliczamy w pętli wg reguły:
x'2 = x2+dx, x = (dx-1)/2 dx' = dx+2
Poniższy program demonstruje tę zasadę wyznaczania kwadratów kolejnych liczb naturalnych od 0 do 15.
|
Uwaga:
Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
Pascal// Wyznaczanie kwadratów
// kolejnych liczb naturalnych
// Data: 2.04.2008
// (C)2020 mgr Jerzy Wałaszek
//---------------=------------
program prg;
var kx, dx, x : integer;
begin
kx := 0; dx := 1;
repeat
x := (dx-1) shr 1;
writeln(x:5, kx:5);
inc(kx, dx); inc(dx, 2);
until x = 15;
writeln;
end. |
// Wyznaczanie kwadratów
// kolejnych liczb naturalnych
// Data: 2.04.2008
// (C)2020 mgr Jerzy Wałaszek
//----------------------------
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int kx, dx, x;
kx = 0; dx = 1;
do
{
x = (dx-1) >> 1;
cout << setw(5) << x
<< setw(5) << kx
<< endl;
kx += dx; dx += 2;
} while(x < 15);
cout << endl;
return 0;
} |
Basic' Wyznaczanie kwadratów ' kolejnych liczb naturalnych ' Data: 2.04.2008 ' (C)2020 mgr Jerzy Wałaszek '---------------------------- Dim As Integer kx, dx, x kx = 0: dx = 1 Do x = (dx-1) Shr 1 Print Using "#### ####";x;kx kx += dx: dx += 2 Loop Until x = 15 Print End |
Python (dodatek)# Wyznaczanie kwadratów
# kolejnych liczb naturalnych
# Data: 12.02.2024
# (C)2024 mgr Jerzy Wałaszek
#---------------------------
kx, dx = 0, 1
while 1:
x = (dx-1) >> 1
print("%4d %4d" % (x, kx))
kx += dx
dx += 2
if x == 15: break
print()
|
| Wynik: |
0 0
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
10 100
11 121
12 144
13 169
14 196
15 225
|
Zastosujmy następującą strategię. Mamy daną liczbę naturalną p, p > 1 i p jest nieparzyste. Obliczamy:
x = ceil(sqr(p)) y = 0 e = x2-y2-p
Liczba e jest wartością błędu pomiędzy x2-y2 a liczbą p. Wyznaczamy przyrosty dla x2 oraz dla y2:
dx = 2x+1 dy = 2y+1 = 1, gdyż początkowo y = 0
Teraz w pętli badamy błąd e. Jeśli jest równy 0, to
p = x2-y2 x = (dx-1)/2 y = (dy-1)/2 m = x+y = (dx-1)/2+(dy-1)/2 = (dx+dy-2)/2 = (dx+dy)/2-1 n = x-y = (dx-1)/2-(dy-1)/2 = (dx-dy)/2
Jeśli n jest różne od 1, to m i n rozkładamy dalej na czynniki tym samym algorytmem. W przeciwnym razie liczba p jest pierwsza, zwracamy ją i kończymy.
Jeśli e jest różne od zera, to nie znaleźliśmy jeszcze x i y spełniających równanie Fermata. Badamy znak e.
Jeśli e > 0, to przeważa x2, zatem zwiększamy y2 i odejmujemy od e przyrost dy. Po tej operacji dy jest zwiększane o 2, aby w kolejnym obiegu otrzymać kwadrat następnego y – a właściwie jego przyrost w stosunku do poprzedniego kwadratu. Zwiększanie y kontynuujemy do momentu, aż e ≤ 0, czyli aż osiągniemy równowagę lub przeważy y2.
Jeśli e < 0, to przeważa y2, zatem zwiększamy x2 i dodajemy do e przyrost dx, który następnie zwiększamy o 2. Operację kontynuujemy do momentu, aż e ≥ 0.
Wracamy na początek pętli, aż do uzyskania e = 0. W tym miejscu
algorytm można zoptymalizować, sprawdzając, czy
x+y ≥ p, czyli
Zwróć uwagę, iż w tej wersji algorytmu Fermata nie wykonujemy w pętli operacji pierwiastkowania, a jedynie proste dodawania. Dzięki temu algorytm staje się dużo szybszy od algorytmu podanego w rozwiązaniu 1.
K01: m ← ceil(sqr(p)) ; wyznaczamy wartość błędu e ' oraz przyrosty dx i dy K02: e ← m2-p ; e = x2-p, ponieważ początkowo y = 0 K03: dx ← 2×m+1 ; dx – przyrost x2 K04: dy ← 1 ; dy – przyrost y2 K05: Dopóki e ≠ 0: ; w pętli staramy się zrównać wykonuj kroki K06…K16 ; x2-y2 z p-wtedy e = 0 K06: Dopóki e > 0: ; przeważa x2, zwiększamy y2 wykonuj kroki K07…K08 K07: e ← e-dy ; modyfikujemy błąd o przyrost y2 K08: dy ← dy+2 ; przyrost y2 dla zwiększonego o 1 y K09: Dopóki e < 0: ; przeważa y2, zwiększamy x2 wykonuj kroki K10…K11 K10: e ← e+dx ; modyfikujemy błąd o przyrost x2 K11: dx ← dx+2 ; przyrost x2 dla zwiększonego x K12: Jeśli (dx+dy)/2 ≤ p, ; sprawdzamy drugi warunek to następny obieg pętli K05 ; zakończenia pętli K13: dx ← 2 ; jeśli jest spełniony, ; to p jest liczbą pierwszą K14: dy ← 0 ; dx i dy ustawiamy, ; tak aby otrzymać n = 1 K15: Idź do kroku K16 ; przerywamy pętlę K05 K16: m ← (dx+dy)/2-1 ; czynnik większy K17: n ← (dx-dy)/2 ; czynnik mniejszy K18: Jeśli n = 1, ; sprawdzamy, czy p jest pierwsze to idź do kroku K21 K19: Fermat(m) ; jeśli nie, to czynniki Fermat(n) ; m i n rozkładamy dalej K20: Zakończ K21: Pisz p ; p jest pierwsze. ; Wyprowadzamy je i kończymy K22: Zakończ
|
Uwaga: Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
| Program w pierwszym wierszu czyta liczbę p i w następnym wierszu wypisuje kolejne czynniki pierwsze tej liczby. Liczba p nie musi być nieparzysta. Przed przekazaniem jej do procedury Fermat program usuwa z p wszystkie czynniki równe 2. |
Pascal// Metoda Fermata
// Data: 2.04.2008
// (C)2020 mgr Jerzy Wałaszek
//---------------------------
uses math;
procedure Fermat(p : int64);
var e, dx, dy, m, n : int64;
begin
m := ceil(sqrt(p));
dx := (m shl 1)+1;
e := m*m-p;
dy := 1;
while e <> 0 do
begin
while e > 0 do
begin
dec(e, dy); inc(dy, 2);
end;
while e < 0 do
begin
inc(e, dx); inc(dx, 2);
end;
if(dx+dy) shr 1 > p then
begin
dx := 2; dy := 0; break;
end;
end;
m := ((dx+dy) shr 1)-1;
n := (dx-dy) shr 1;
if n > 1 then
begin
Fermat(m); Fermat(n);
end
else write(p, ' ');
end;
var p : int64;
begin
readln(p);
while p mod 2 = 0 do
begin
write(2, ' ');
p := p shr 1;
end;
if p > 1 then
Fermat(p);
writeln;
end. |
C++// Metoda Fermata
// Data: 2.04.2008
// (C)2020 mgr Jerzy Wałaszek
//---------------------------
#include <cstdlib>
#include <iostream>
#include <cmath>
using namespace std;
void Fermat(long long p)
{
long long e, dx, dy, m, n;
m = (long long)sqrt(p);
dx = (m << 1)+1;
e = m*m-p;
dy = 1;
while(e != 0)
{
while(e > 0)
{
e -= dy; dy += 2;
}
while(e < 0)
{
e += dx; dx += 2;
}
if(((dx+dy) >> 1) > p)
{
dx = 2;
dy = 0;
break;
}
}
m = ((dx+dy) >> 1)-1;
n = (dx-dy) >> 1;
if(n != 1)
{
Fermat(m); Fermat(n);
}
else cout << p << " ";
}
int main()
{
long long p;
cin >> p;
while(p % 2 == 0)
{
cout << 2 << " ";
p >>= 1;
}
if(p > 1) Fermat(p);
cout << endl;
return 0;
} |
Basic' Metoda Fermata
' Data: 2.04.2008
' (C)2020 mgr Jerzy Wałaszek
'---------------------------
Sub Fermat(Byval p As Longint)
Dim As Longint e, dx, dy, m, n
m = Clngint(Sqr(p))
dx = (m Shl 1)+1
e = m*m-p
dy = 1
While e
While e > 0
e -= dy: dy += 2
Wend
While e < 0
e += dx: dx += 2
Wend
If (dx+dy) Shr 1 > p Then
dx = 2
dy = 0
Exit While
End If
Wend
m = ((dx+dy) Shr 1)-1
n = (dx-dy) Shr 1
If n > 1 Then
Fermat(m): Fermat(n)
Else
Print p;" ";
End If
End Sub
Dim p As Longint
Input p
While p Mod 2 = 0
Print 2;" ";
p = p Shr 1
Wend
If p > 1 Then _
Fermat(p)
Print
End |
Python (dodatek)# Metoda Fermata
# Data: 12.02.2024
# (C)2024 mgr Jerzy Wałaszek
# --------------------------
import math
def fermat(p):
m = int(math.sqrt(p))
dx = (m << 1)+1
e = m*m-p
dy = 1
while e:
while e > 0:
e -= dy
dy += 2
while e < 0:
e += dx
dx += 2
if ((dx+dy) >> 1) > p:
dx, dy = 2, 0
break
m = ((dx+dy) >> 1)-1
n = (dx-dy) >> 1
if n != 1:
fermat(m)
fermat(n)
else:
print(p, end=" ")
return
p = int(input())
while not (p % 2):
print(2, end=" ")
p >>= 1
if p > 1:
fermat(p)
print()
|
| Wynik: |
| 254821743888 2 2 2 2 230816797 23 3 |
Większość liczb złożonych posiada czynniki pierwsze o małych wartościach. Algorytm Fermata jest szczególnie wydajny dla czynników leżących w pobliżu pierwiastka rozkładanej liczby. Natomiast czynniki małe są znajdowane wolno. Proponowane tutaj ulepszenie polega na połączeniu algorytmu próbnych dzieleń z algorytmem Fermata. W tablicy przechowujemy kolejne liczby pierwsze od 2 do 1009 – jest ich 169. Przed przekazaniem liczby p do procedury Fermat, z liczby p usuwamy wszystkie czynniki pierwsze przechowywane w tablicy. Jeśli liczba posiada takie czynniki, to po usunięciu ich staje się dużo mniejsza – zatem algorytm Fermata szybciej znajdzie pozostałe, duże czynniki pierwsze. Czas wykonania 169 próbnych dzieleń jest bardzo mały dla współczesnych procesorów, zatem warto zastosować to ulepszenie.
|
Uwaga: Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
Pascal// Metoda Fermata
// Data: 2.04.2008
// (C)2020 mgr Jerzy Wałaszek
//---------------------------
uses math;
procedure Fermat(p : int64);
var e, dx, dy, m, n : int64;
begin
m := ceil(sqrt(p));
dx := (m shl 1)+1;
e := m*m-p;
dy := 1;
while e <> 0 do
begin
while e > 0 do
begin
dec(e, dy); inc(dy, 2);
end;
while e < 0 do
begin
inc(e, dx); inc(dx, 2);
end;
if (dx+dy) shr 1 > p then
begin
dx := 2;
dy := 0;
break;
end;
end;
m := ((dx+dy) shr 1)-1;
n := (dx-dy) shr 1;
if n > 1 then
begin
Fermat(m); Fermat(n);
end
else write(p, ' ');
end;
const lp : array [0..168] of integer = (
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269,
271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383,
389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499,
503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619,
631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751,
757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881,
883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009);
var
p : int64;
i : integer;
begin
readln(p);
for i := 0 to 168 do
begin
if p >= lp[i] then
while p mod lp[i] = 0 do
begin
write(lp[i], ' ');
p := p div lp[i];
end
else break;
end;
if p > 1 then Fermat(p);
writeln;
end. |
C++// Metoda Fermata
// Data: 2.04.2008
// (C)2020 mgr Jerzy Wałaszek
//---------------------------
#include <cstdlib>
#include <iostream>
#include <cmath>
using namespace std;
void Fermat(long long p)
{
long long e, dx, dy, m, n;
m = (long long)sqrt(p);
dx = (m << 1)+1;
e = m*m-p;
dy = 1;
while(e != 0)
{
while(e > 0)
{
e -= dy; dy += 2;
}
while(e < 0)
{
e += dx; dx += 2;
}
if(((dx+dy) >> 1) > p)
{
dx = 2;
dy = 0;
break;
}
}
m = ((dx+dy) >> 1)-1;
n = (dx-dy) >> 1;
if(n != 1)
{
Fermat(m); Fermat(n);
}
else cout << p << " ";
}
int main()
{
const int lp[] = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269,
271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383,
389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499,
503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619,
631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751,
757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881,
883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009};
long long p;
int i;
cin >> p;
for(i = 0; i < 169; i++)
{
if(p >= lp[i])
while(p % lp[i] == 0)
{
cout << lp[i] << " ";
p /= lp[i];
}
else break;
}
if(p > 1) Fermat(p);
cout << endl;
return 0;
} |
Basic' Metoda Fermata
' Data: 2.04.2008
' (C)2020 mgr Jerzy Wałaszek
'---------------------------
Sub Fermat(Byval p As Longint)
Dim As Longint e, dx, dy, m, n
m = Clngint(Sqr(p))
dx = (m Shl 1)+1
e = m*m-p
dy = 1
While e
While e > 0
e -= dy: dy += 2
Wend
While e < 0
e += dx: dx += 2
Wend
If (dx+dy) Shr 1 > p Then
dx = 2
dy = 0
Exit While
End If
Wend
m = ((dx+dy) Shr 1)-1
n = (dx-dy) Shr 1
If n > 1 Then
Fermat(m): Fermat(n)
Else
Print p;" ";
End If
End Sub
Dim lp(168) As Integer => {_
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, _
71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, _
167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, _
271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, _
389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, _
503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, _
631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, _
757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, _
883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009}
Dim p As Longint, i As Integer
Input p
For i = 0 To 168
If p >= lp(i) Then
While p Mod lp(i) = 0
Print lp(i);" ";
p \= lp(i)
Wend
Else
Exit For
End If
Next
If p > 1 Then Fermat(p)
Print
End |
Python (dodatek)# Metoda Fermata
# Data: 12.02.2024
# (C)2024 mgr Jerzy Wałaszek
# --------------------------
import math
def fermat(p):
m = int(math.sqrt(p))
dx = (m << 1)+1
e = m*m-p
dy = 1
while e:
while e > 0:
e -= dy
dy += 2
while e < 0:
e += dx
dx += 2
if (dx+dy) >> 1 > p:
dx = 2
dy = 0
break
m = ((dx+dy) >> 1)-1
n = (dx-dy) >> 1
if n > 1:
fermat(m)
fermat(n)
else:
print(p, end=" ")
return
lp = [ \
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, \
71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, \
167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, \
271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, \
389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, \
503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, \
631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, \
757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, \
883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009]
p = int(input())
for i in range(169):
if p >= lp[i]:
while not (p % lp[i]):
print(lp[i], end=" ")
p //= lp[i]
else:
break
if p > 1:
fermat(p)
print()
|
| Wynik: |
1234567891011 3 7 13 67 107 630803 1111111111111111 11 17 73 101 137 5882353 222222222222222222 2 3 3 7 11 13 19 37 333667 52579 |
![]() |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2026 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.