Ecuatii diofantice

Rezolvarea ecuatiilor diofantice

Orice congruenta ax1+cs0 (mod b) se poate scrie ca o ecuatie ax1+bx2+c=0 (in care a¹ 0), b³1 si c, x1, x2 sunt numere intregi. Daca a, b, c sunt numere intregi date si x1 si x2 sunt considerate necunoscute, problema se reduce la gasirea solutiilor intregi ale unei ecuatii liniare cu coeficienti intregi. Daca f(x1,…, xn) este un polinom in x1,…, xn cu coeficienti intregi, atunci ecuatia f(x1,…, xn) = A se numeste diofantica daca solutiile ei sunt numere intregi. Denumirea acestor ecuatii deriva de la numele matematicianului grec Diofantos din Alexandria. Daca o astfel de ecuatie admite solutii, atunci ea admite o infinitate de n-upluri care o satisfac.

In continuare se va trata cazul n=2: ax+by=c

Daca a si b sunt numere prime intre ele si x0, y0 constituie o solutie pentru ax+by=c, atunci totalitatea solutiilor se poate reprezenta sub forma: x= x0+bt, y= y0 –at, unde t este un numar intreg oarecare. O solutie a ecuatiei se poate obtine cu ajutorul penultimei fractii de aproximare pentru reprezentarea sub forma de fractie continua a lui a/b. Considerand ca penultima fractie este m/n, x0=nc, y0=-mc.

Exemplu:

Fie ecuatia: de aproximare ale lui sunt: 7/3, 9/4, fractia 9/4 se obtine x0=4*2=8, y0=-9*2=-18. Astfel, solutia generala se poate scrie de forma: x=8+19t si y=-18-unde t este un numar oarecare.

Implementare

Algoritmul de mai sus este valabil, dupa cum am precizat, in cazul cand cele 2 numere a si b sunt prime intre ele. Daca dorim rezolvarea unei ecuatii in care cele 2 numere nu sunt neaparat prime intre ele, se poate proceda in felul urmator: se calculeaza cel mai mare divizor comun al lor (sigur este diferit de 1), iar apoi se evalueaza daca ecuatie poate sau nu avea solutii, in functie de valoarea lui c. Daca c este divizibil cu cmmdc-ul celor 2 numere, atunci se simplifica intreaga ecuatie cu cmmdc si problema se reduce la cea prezentata mai sus. Daca c nu se imparte exact la cmmdc, atunci putem spune ca ecuatia nu are solutii intregi.

Pe langa aceasta, intervin o serie de cazuri critice in care algoritmul de mai sus nu poate fi aplicat, cum ar fi de exemplu cazurile in care nu exista penultima fractie. Dar se poate calcula solutia si in aceste cazuri:

a=0, b=0

In acest caz solutia depinde valoarea lui c:

c=0 => x si y poate fi orice numar intreg

c ¹ 0 => nu exista solutii

a=0, b¹ 0

Ecuatia devine: by=c. Deci y se poate calcula, tinand insa cont ca vorbim numai de numere intregi.

a¹0, b= 0

Analog cu cazul anterior.

Daca unul dintre numerele a sau b are valoarea 1 nu se mai poate vorbi de penultima fractie de aproximare, deci si aceste cazuri trebuie tratate separat.

O alta observatie este aceea ca fractia de aproximare (m/n) aproximeaza fractia (a/b) in plus sau in minus. De aceea in la sfarsit trebuie sa corectez rezultatul in functie de aceasta, tinand seama si de semnul fractiei a/b.

Sursa programului

#include

#include

#include

long int v[100];

//obtine penultima fractie de aproximare

void get_mn(long int &a,long int &b,int k)

{

if (k>0) { long int aux=v[k-1]*b+a;

a=b;b=aux; dm8

get_mn(a,b,k-1);

}

else a=a+b-(b=a);

}

long int _cmmdc(long int a,long int b)

{

while (a!=b)

if (a>b) a-=b;

else b-=a;

return a;

}

void stop()

{

printf("Nu exista solutii...\n");

}

int solutii(long int a,long int b,long int c,

long int &x0,long int &n1,long int &y0,long int &n2)

{

long int m,n,cmmdc=1,_a,_b;

int nr=-1;

_a=labs(a);_b=labs(b);

if ((_a>1)&&(_b>1)) cmmdc=_cmmdc(_a,_b);

if (cmmdc!=1){

if (c%cmmdc) {stop();return 0;}

else a/=cmmdc,b/=cmmdc,c/=cmmdc;

}

m=a;n=b;

if (!(a*b))

if (!a) if (!b)

{

//0=c

if (!c) printf("x,yIZ\n");

else stop();

return 0;

}

else

{ // by=c

if (c%b) stop();

else { printf("xIZ\n");

printf("y=%ld\n",c/b);

}

return 0;

}

else

{ //ax=c

if (c%a) stop();

else {printf("x=%ld\n",c/a);

printf("yIZ\n");

}

return 0;

}

if (labs(m)==1)

{ // inseamna ca este de forma ±x+b*y=c, deci nu exista

// penultima fractie de aproximare

x0=c*m;n1=-b*m;

y0=0;n2=1;

return 1;

}

else

if (labs(n)==1)

{ // inseamna ca este de forma a*x±y=c, deci nu exista

// penultima fractie de aproximare

x0=0;n1=1;

y0=c*n;n2=-a*n;

return 1;

}

// m si n sunt diferite de 1, si diferite intre ele

m=labs(m);n=labs(n);

while (m!=1){

if (m>n){ v[++nr]=m/n;

m-=m/n*n;

}

else if (m

}

n=v[nr];

get_mn(m,n,nr);

if (_a<_b) m=m+n-(n=m);

//in functie de fractia de aproximare corectez rezultatul

if (a*b>0) if (_a*n<_b*m) c=-c;

if (a*b<0) if (_a*n>_b*m) c=-c;

if (a<0) m=-m;

if (b<0) n=-n;

x0=n*c;n1=b;

y0=-m*c;n2=-a;

return 1;

}

void main(void)

{

long int a,b,c,x0,y0,n1,n2;

do{

clrscr();

puts("Se rezolva ecuatia: ax+by=c, a,b,x,y,ciZ");

printf("a=");scanf("%ld",&a);fflush(stdin);

printf("b=");scanf("%ld",&b);fflush(stdin);

printf("c=");scanf("%ld",&c);fflush(stdin);

printf("----------------------------------------\n");

if (solutii(a,b,c,x0,n1,y0,n2)){

if (!x0) if (labs(n1)!=1) printf("x=%ldt\n",n1);

else printf("x=%st\n",n1<0?"-":"");

else if (labs(n1)!=1) printf("x=%ld%+ldt\n",x0,n1);

else printf("x=%ld%st\n",x0,n1<0?"-":"");

if (!y0) if (labs(n2)!=1) printf("y=%ldt\n",n2);

else printf("y=%st\n",n2<0?"-":"");

else if (labs(n2)!=1) printf("y=%ld%+ldt\n",y0,n2);

else printf("y=%ld%st\n",y0,n2<0?"-":"");

printf("unde t este un numar intreg\n");}

puts("Apasati o tasta (x pentru a termina)...");

c=getch();

}while (c!='x');

}

download