Na początku grudnia opublikowałem zarys algorytmu, w którym podstawową ideą jest utworzenie płaszczyzny z liczby, oraz szukanie śladu dzielników dla dużych wartości.
Na razie coś mnie blokuje przed napisaniem tego w C++, ale jest już wersja w Pythonie.
Miałem kłopoty, jak szybko ominąć część kodu po znalezieniu małego dzielnika. Zdecydowałem się na pętlę.
[code python]
def nwd(a,b,s):
if( 0==b ):
return a
if( a<b ): #swap(a,b)
c=a
a=b
b=c
while( 1 ): # zmniejszamy b, bo wiemy, ze sa one wzglednie pierwsze
if( 0==b%2 ):
b/=2
continue
if( 0==b%3 ):
b/=3
continue
if( 0==b%5 ):
b/=5
continue
if( 0==b%7 ):
b/=7
continue
break
if( 0==a%b ):
return b
a = a%b
if( a+a>b ) :
a = b-a
if( s>a ): #zatrzyma: wiemy ze nie ma tak malych dzielnikow
return 1
return nwd(b,a,s)
def modstop(s):
# zwieksza s do najblizszej liczby nieparzystej nie podzielnej przez 3, 5, 7
while( 1 ):
s+=2
if( 0==s%3 ):
continue
if( 0==s%5 ):
continue
if( 0==s%7 ):
continue
#break
return s
s=7 # lub wiecej, jesli jestesmy pewni
n= duza liczba
a=int (sqrt n) # jak to policzyc na liczbach calkowitych?
#a=int (n**(0.5)) # blad w liczeniu pozniejszych operacji
b= 1+(n-a*a)//a
c= n-(a+b)*a # w algorytmie c<0, trzymamy je jako ujemna wartosc
print a,b,c, (a+b)*a+c # sprawdzenie niezmiennika (a+b)*a+c = n
while( 1 ):
if( 0==n%2 ): # male dzielniki
n /=2
print "Dzielnik 2"
break
if( 0==n%3 ):
n/=3
print "Dzielnik 3"
break
if( 0==n%5 ):
n/=5
print "Dzielnik 5"
break
if( 0==n%7 ):
n/=7
print "Dzielnik 7"
break
while ( 1 ):
f = a%s # obliczenie (a+b)*a+c modulo s czyli spr. male dzielniki
e = ((f+b)*f+c)%s
if( 0==e ):
print "Dzielnik z modulo ",s
break
s = modstop(s) # zwiekszenie s
e = nwd(a,-c,s) # nwd wyrazu wolnego i podstawy systemu
if( 1<e ):
print "Dzielnik ze sladu ",e
break;
a-=1 # pelni role podstawy systemu, zmniejszamy o 1
b+=2 # wyrugowanie wplywu podstawy na wyraz wolny
c+=b-1 # modyfikacja wyrazu wolnego
if( 0==c ) :
print "Dzielnik z wyrazu wolnego ",a
break
if( 0<c ) : // wyraz wolny wiekszy niz podstawa a
b+=1
c-=a
#mozna wypisac - dla testow
#print "liczba (1*",a,"+",b,")*",a,c," stop = ",s
if( s>a ) : # duze lub male dzielniki nie znalezione, brak mozliwosci innych
print "Liczba pierwsza ",n
break
break
[\code python]
Dla malych wartosci dziala. Dla liczby 90-bitowej po dobie liczenia iloraz wartosci do sprawdzenia do oszacowania dzielnika z dołu jest mniejszy niż 2000, następnego dnia poniżej 1000. Sprawdzane są równocześnie małe i duże kandydaci, dlatego zakres możliwości się zmniejsza z obu stron.
Drugiego dnia zostało sprawdzone około 0,1% wszystkich możliwości, zastosowany wzór: iloraz różnicy podstawy a i minimalnej możliwej liczby pierwszej s przez liczność początkową (a-s)/(sqrt n). Można zatem spróbować oszacować czas przebiegu na tej maszynie na kilkaset dni. Choć podejrzewam istnienie przedziałów, w których po wejściu do nwd nastąpi od razu wyjście ( bo |c|<s ).
Mam jeszcze jeden pomysł związany z tą płaszczyzną, choć będzie wymagał sporo pamieci i moze być nieefektywny. Przechowywanie podstawy w postaci docelowo kanonicznej... Jako skutek uboczny pojawi się tablica liczb pierwszych.
Brak komentarzy:
Prześlij komentarz