9 novembre 2011

annuncio pubblicitario
Teoria dei numeri e Crittografia: lezione del 9 novembre 2011
Il seguente risultato permette di ricondurre il calcolo di (n) al calcolo dei (d) con d<n:
Teorema.
Per ogni naturale n>1 si ha n =
 (d )
(e in particolare (n)=n -
d n
1 d  n
  (d ) ).
d n
1 d  n
Dimostrazione:
Sia A = { dN / dn }. E’ facile verificare che la funzione f: A  A definita da f(d)=n/d è iniettiva,
quindi biunivoca perché A è finito.
Per ogni dA sia Ad = { xN / 1xn , mcd(x,n)=d }: tale insieme è non vuoto perché dAd .
Al variare di dA gli insiemi Ad formano una partizione di {1,2….,n}: ogni elemento x{1,2….,n}
appartiene a qualche Ad (basta scegliere d=mcd(x,n)) e ovviamente, se c,dA sono distinti, gli
insiemi Ad, Ac non hanno elementi comuni (se xAdAc si avrebbe d=mcd(x,n)=c).
Si deduce allora che
n = {1,2,….,n}= Ad
dA
Fissato dA, sia Bd = { xN / 1xn/d ; x, n/d coprimi }. Definiamo la funzione g : Ad  Bd
ponendo g(x)=x/d (notare che x/dBd in quanto x/d, n/d sono coprimi perché d=mcd(x,n)).
Tale funzione è biunivoca: l’iniettività è banale, mentre per la surgettività basta osservare che se
yBd, allora x=ydAd (è facile verificare che dall’ipotesi y, n/d coprimi segue che mcd(x,n)=d) e
dunque g(x)=y.
Si conclude allora che Ad=Bd= (n/d).
Sfruttando la funzione biunivoca f. A  A definita sopra, si ha che A=f(A)={ n/d / dA }, da cui
per la proprietà commutativa della somma di interi:
n = Ad= Bd=   (n / d ) =   ( f (d )) =   (d ) e si ha la tesi.
dA
dA
d A
d A
d A
Algoritmo per il calcolo della parte intera della radice n-esima
Fissato un numero naturale n>1, costruiamo un algoritmo nroot(a) che, dato in input il numero
naturale a (radicando) , calcoli la parte intera di n a , ossia il più grande numero naturale y tale che
y n a (equivalentemente il più grande numero naturale y tale che yn a).
Supponendo x=L(a), si ha 2x-1 a<2x .
Se n x allora 2n2x>a dunque n a < 2, e la parte intera della radice n-esima di a è =1.
Possiamo allora supporre n<x .
Rappresentiamo a in base 2, e raggruppiamo le sue x cifre binarie in k blocchi (ognuno di n cifre
binarie) :
a = 12……k
Dunque ogni i è un blocco di n cifre binarie (aggiungiamo eventualmente degli zeri a sinistra per
rendere anche il primo blocco 1 di n cifre): tratteremo ogni blocco i come un valore numerico
intero  0 (rappresentato in base 2).
Si ha ovviamente 0 i< 2n per ogni i=1,….,k, essendo ogni i un blocco di n cifre binarie (quindi,
come valore numerico, di lunghezza binaria  n, tenendo conto che vi possono essere all’inizio del
blocco alcuni bits nulli ). Inoltre certamente almeno 1 è >0.
Descriviamo il seguente algoritmo nroot(a) che genera 2 successioni di numeri interi  0:
yi , xi (con i=0,1,…,k)
1) Si pone y0=x0=0
2) Per i=1,….,k si ripete il seguente blocco di istruzioni (che calcola il valore yi in funzione del
valore precedente yi-1):
a) Si calcola la massima cifra binaria {0,1} tale che (2yi-1+)n 2nxi-1+i
b) Si pone yi=2yi-1+, xi=2nxi-1+i
3) l’algoritmo esce con output “yk = parte intera di n a ”.
Facciamo alcune osservazioni che saranno utili.
Esaminando le istruzioni a),b) del ciclo 2) si nota che:
yin xi per ogni i=0,1,…..,k (*)
Osserviamo anche che nel passo a) del ciclo 2), affinchè l’istruzione possa essere eseguita, si deve
essere certi che valga per ogni i=1,…..,k la disuguaglianza:
(2yi-1)n 2nxi-1+i (**)
(se fosse (2yi-1)n> 2nxi-1+i a maggior ragione si avrebbe (2yi-1+1)n> 2nxi-1+i e nessuna delle cifre
binarie {0,1} avrebbe la proprietà (2yi-1+)n 2nxi-1+i).
La (**) si ricava facilmente dalla (*) in quanto, posto j=i-1, si ha:
(2yi-1)n=2nyi-1n  2nxi-1 2nxi-1+i (essendo i  0).
Esaminando inoltre l’algoritmo si vede che ad ogni iterazione nel passo 2) il numero xi si ottiene
shiftando verso sinistra il numero xi-1 di n posizioni, e aggiungendo alla sua destra il blocco i :
quindi, partendo dal valore iniziale x0=0, è ovvio che alla fine del ciclo si avrà:
xk=12……k = a (radicando).
D’altro canto il numero yi si ottiene shiftando verso sinistra il numero yi-1 di 1 posizione e
aggiungendo alla sua destra la cifra binaria  trovata nel passo a): quindi, partendo dal valore
iniziale y0=0, è ovvio che le varie cifre binarie  trovate in successione nella iterazione della a) sono
proprio le cifre binarie dell’output yk .
Resta da dimostrare che effettivamente (come dice l’output) si ha:
yk = parte intera di n a ossia yk è il massimo intero tale che yk n a.
Applicando la (*) per i=k si ha:
ykn xk=a.
Basta allora dimostrare che (yk+1)n > a .
Dimostriamo che per ogni i=1,2,…,k si ha:
(yi+1)n > xi (***)
Ragioniamo per induzione (Ia forma).
Per i=1 (***) è vero, perché il valore della cifra  nella a) è in questo caso =1 (in quanto
(2y0+1)n=1 2nx0+1=1
perché, come già notato, si ha 1>0) dunque y1=2y0+1=1,
n
n
x1=2 x0+1=1 , 1 =11.
Supponiamo (***) vero per i, e dimostriamolo vero per i+1.
Dunque supponiamo che (yi+1)n > xi , e dimostriamo che (yi+1+1)n > xi+1 .
Se nell’iterazione i+1 al passo a) il valore della cifra  è 0 (quindi se (2yi+1)n>2nxi+i+1 ) allora la
tesi è ovvia perché appunto yi+1=2yi+=2yi, xi+1=2nxi+i , (yi+1+1)n=(2yi+1)n>2nxi+i+1 = xi+1 .
Se invece nell’iterazione i+1 il valore della cifra  è 1, si ha (tenendo conto che dall’ipotesi
induttiva (***) segue (yi+1)n  xi+1) :
yi+1+1=2yi+2, xi+1=2nxi+i , (yi+1+1)n=(2yi+2)n=2n(yi+1)n2n (xi+1)=2nxi+2n>2nxi+i=xi+1
da cui la (***) è vera anche per i+1 (si è sfruttato il fatto che i< 2n) .
In particolare da (***) per i=k si ottiene:
(yk+1)n > xk = a
e possiamo concludere che l’output yk è effettivamente il più grande numero naturale y tale che la
yn a , quindi yk è la parte intera di n a .
Resta da esaminare la complessità di calcolo dell’algoritmo nroot(a), in funzione di x=L(a).
Le uniche operazioni non trascurabili sono eseguite nel ciclo 2), quando si deve calcolare la
potenza:
(2yi-1+)n= yin
(le altre operazioni si riducono a degli shift con inserimento di cifre binarie in coda, oppure al
confronto di numeri binari per decidere il valore di , e si possono considerare trascurabili).
La potenza yin si può calcolare eseguendo n-1 prodotti della forma yi j-1yi con j=1,…,n-1 (prodotti in
cui entrambi i fattori sono  yin ykn=a, quindi di lunghezza ≤ x): ognuno di tali prodotti si può
eseguire con un algoritmo di complessità di ordine O(x2). Ricordando, come detto all’inizio, che
siamo nell’ipotesi n<x, il numero di tali prodotti è di ordine O(x), dunque il calcolo della potenza yin
si può eseguire con un algoritmo di complessità di ordine O(x3).
Infine il ciclo 2) dell’algoritmo viene eseguito k volte, dove k è il numero dei blocchi (di n cifre
binarie ciascuno) in cui sono state divise le x cifre binarie di a: si ha perciò k<x dunque k è di ordine
O(x) e complessivamente l’algoritmo nroot(a) ha complessità di ordine O(x4), dove x è la lunghezza
binaria del radicando a.
L’algoritmo nroot(a) (per il calcolo della parte intera di n a ) si può trasformare facilmente in un
algoritmo che risponda al quesito: fissato il numero naturale n>1 e dato in input il numero naturale
a, il numero a è una “potenza n-esima perfetta” cioè a coincide con la potenza di esponente n di un
opportuna base intera ? (per esempio potremmo eseguire un test per decidere se a è un quadrato
perfetto, un cubo perfetto etc…..).
Infatti basta calcolare con l’algoritmo nroot(a) la parte intera yk di n a , ed verificare se essa coincida
esattamente con n a : quindi basta aggiungere all’algoritmo una istruzione che esegua il calcolo
della potenza ykn e verifichi se il risultato è =a : in caso affermativo a è una potenza n-esima esatta
di base intera (e la base è proprio yk), in caso negativo non lo é.
Tale algoritmo ha anch’esso complessità di ordine O(x4): infatti si deve aggiungere all’algoritmo
nroot(a) solo il calcolo della potenza ykn che, come visto in precedenza quando si esaminava il
calcolo delle potenze yin , ha complessità di ordine O(x3) .
Infine possiamo notare che si può costruire un algoritmo che risponda al quesito: dato in input un
numero naturale a, il numero a coincide con la potenza di esponente n di un opportuna base intera,
per un opportuno esponente intero n>1 (notare che n non è fissato a priori).
Infatti (tranne nel caso banale a=1) un eventuale valore dell’esponente n>1 (se esiste) è certamente
<x=L(a) (come già notato nella lezione precedente, se n x allora la parte intera di n a è =1 quindi
in tale caso a è potenza n-esima di base naturale solo per a=1): quindi basta ripetere l’algoritmo
precedente per tutti gli n con 2 n<x: se per nessuno di tali valori il test dà esito positivo, possiamo
concludere con certezza che l’input a non è potenza di un opportuna base intera, per nessun
esponente n>1; se invece per qualcuno di tali valori n il test dà esito positivo, abbiamo trovato che
per quel valore dell’esponente n il numero a è potenza di un opportuna base intera.
Poiché l’algoritmo precedente ha complessità di ordine O(x4) ed esso viene ripetuto (nel caso
peggiore) un numero x-2 di volte (quindi un numero di volte di ordine O(x)) , complessivamente
questo algoritmo ha complessità polinomiale di ordine O(x5).
Algoritmo per la soluzione di sistema somma-prodotto.
Supponiamo che p, q siano due numeri naturali di cui si conoscono somma a=p+q, e prodotto
n=pq.
Costruiamo un algoritmo per calcolare, dati in input a, n, i valori di p, q.
Supponiamo per fissare le idee p q.
Se x=L(n), si ha a n tranne nel caso banale p=q=1: infatti da pq2 si ha a=p+q2ppq=n .
Possiamo dunque supporre a n e dunque L(a) x.
E’ ben noto che p, q sono soluzioni dell’equazione di secondo grado:
x2 – ax + n = 0
dunque (essendo p q):
p =( a+ 2 d )/2, p =( a- 2 d )/2 dove d = a2- 4n.
In tale algoritmo, tranne le moltiplicazioni per 4 e le divisioni per 2 (che si ottengono con semplici
aggiunte o cancellazioni di cifre binarie 0 a destra), le uniche operazioni non trascurabili sono il
calcolo di d = a2- 4n, l’estrazione di 2 d , la somma (o differenza) di a e 2 d .
Il calcolo di a2 si può eseguire con un algoritmo di complessità di ordine O(x2); poiché L(a2) 
2L(a)  2x, L(4n)=2+L(n)=2+x, il calcolo di d = a2- 4n si può eseguire con un algoritmo di
complessità di ordine O(x); poiché L(d)  L(a2)  2x, il calcolo di 2 d (che sarà per ipotesi un
numero naturale quindi coinciderà con la sua parte intera) si può eseguire con l’algoritmo 2root(d)
di complessità di ordine O(x4) (vedere paragrafo precedente); infine il calcolo della somma (o
differenza) di a e 2 d si potrà eseguire con un algoritmo di complessità di ordine O(x).
In totale il calcolo dei numeri p,q si potrà eseguire con un algoritmo di complessità polinomiale di
ordine O(x4): ciò completa le considerazioni fatte in precedenza sulla funzione di Eulero e la
fattorizzazione unica.
Scarica