Pagini: [1]   În jos
  Imprimă  
Ajutor Subiect: Divizori  (Citit de 31271 ori)
0 Utilizatori şi 1 Vizitator pe acest subiect.
tErMy
Strain


Karma: 1
Deconectat Deconectat

Mesaje: 7



Vezi Profilul
« : Ianuarie 13, 2008, 11:12:20 »

    Salut! 
    Am dat peste o problema care necesita numarul de divizori al unui numar mare ( maxim 2 miliarde ).
Metoda clasica ( for (i=2; i<=n/2; i++) if (n%i==0) nrdivizori++ ) depaseste timpul . M-am uitat pe indicatii si acolo scria ca este necesar un program care genereaza numere prime si descompun nr in numere prime.. insa fac informatica doar de aproximativ 6 luni si nu stiu sa fac prea bine astea .
    Ceea ce va rog este sa imi aratati un model de algoritm care afla numarul de divizori al unui numar sau sa ma ajutati sa inteleg metoda pe care am pomenit-o mai sus pentru ca la nivelul la care sunt acum ma depaseste.
    Multumesc !
Memorat
Florian
Nu mai tace
*****

Karma: 125
Deconectat Deconectat

Mesaje: 832



Vezi Profilul
« Răspunde #1 : Ianuarie 13, 2008, 11:33:56 »

Pai..sa presupunem ca ai numerele prime pana la 2 miliarde in vectorul a[] (acestea sunt aproximativ in nr de 45.000 cred]. [Le poti genera prin eratostene -vezi la articolele de pe site, sau daca nu, metoda clasica].
Formula pt numarul divizorilor este: nr_divizori= (1+r1)*(1+r2)* ... (1+rk), unde r1,r2,..rk sunt puterile la care apar factorii primi p1,p2, ... respectiv, pk, in descompunerea lui N [unde N=nr al carui nr de divizori tre sa il afli].
Ideea e, ca la factorizarea [descompunerea] lui N sa vezi de cate ori se imparte N la fiecare din elementele vectorului a[], astfel factorizarea fiind mult mai rapida, si capatand complexitate O(sqrt(N)).

ps: Daca nu stii sa implementezi, da`mi un pm cu id-ul de messenger, si te ajut cu placere.  Ok
Memorat
sims_gl
Client obisnuit
**

Karma: 35
Deconectat Deconectat

Mesaje: 53



Vezi Profilul
« Răspunde #2 : Ianuarie 13, 2008, 12:36:17 »

Florian, ai o mica greseala. Numerele prime pana la 2 miliarde sunt mult mai multe decat 45000 [si chiar daca ar fi doar atatea, pana si ciurul lui eratostene are complexitate O(NlogN) si memorie O(N), si nu s-ar incadra in nici una]. Numai ca le folosesti doar pe cele pana la sqrt(N) [adik radical din N, Andrei, daca nu stiai ce inseamna]. Si intradevar sqrt(N) = 45000, iar numerele prime sunt mai putine decat atat. Ideea e ca un numar N poate avea cel mult un divizor prim mai mare decat radicalul lui [daca vrei o sa incerc sa-ti si demonstrez]. Asa ca imparti N la fiecare numar prim din cele aflate si afli puterile la care se referea Florian, si daca dupa impartiri N > 1, atunci N este numar prim si are puterea 1.
Andrei, sper ca ai inteles! Daca mai ai intrebari, o sa-ti raspund cu placere.
« Ultima modificare: Ianuarie 13, 2008, 12:41:40 de către Alexandru Simion » Memorat

"I want to know god's thoughts... the rest are details." Einstein
Prostu
Nu mai tace
*****

Karma: 134
Deconectat Deconectat

Mesaje: 323



Vezi Profilul
« Răspunde #3 : Ianuarie 13, 2008, 14:05:14 »

Nu este nevoie de ciurul lui Eratostene. Este de ajuns sa numeri de 2 ori fiecare divizor pana la sqrt(N), avand grija sa scazi 1 daca numarul e patrat perfect.
Fie N, numarul dat si d un divizor al sau, atunci si N / d este divizor al lui N. Pentru a nu numara divizorii de 2 ori, vom pune constrangerea ca d < N / d, care este echivalent cu d < sqrt(N).
Cod:
stop = sqrt(N);
for (i = 2; i <= stop; ++i)
    if (N % i == 0) nrdivizori += 2;
if (stop * stop == N) --nrdivizori;
Memorat
wefgef
Nu mai tace
*****

Karma: 1049
Deconectat Deconectat

Mesaje: 3.008


razboinicu' luminii


Vezi Profilul
« Răspunde #4 : Ianuarie 13, 2008, 14:07:31 »

Prostule, ai uitat sa numeri divizorii 1 si N.
Memorat

omului i-au fost date instinctele pentru a supravietui, nu pentru a fi sclavul lor.
Prostu
Nu mai tace
*****

Karma: 134
Deconectat Deconectat

Mesaje: 323



Vezi Profilul
« Răspunde #5 : Ianuarie 13, 2008, 14:11:37 »

Din postul lui initial am inteles ca vrea numai divizorii proprii, [for (i = 2...].
Memorat
Florian
Nu mai tace
*****

Karma: 125
Deconectat Deconectat

Mesaje: 832



Vezi Profilul
« Răspunde #6 : Ianuarie 13, 2008, 14:27:31 »

Prostule, ai uitat sa numeri divizorii 1 si N.
Ce fain suna.  Tongue
Memorat
tErMy
Strain


Karma: 1
Deconectat Deconectat

Mesaje: 7



Vezi Profilul
« Răspunde #7 : Ianuarie 13, 2008, 15:30:00 »

in problema am de aflat numarul de divizori al tuturor numerelor din intervalul [a;b] ( b-a<= 10.000 si valoarea maxima a lui b e de 2 miliarde ) si imi trebuie un algoritm care nu executa multe oeratii pentru fiecare numar...
Am vorbit cu Florian pe mess si ma ajutat la segventa de aflat numarul de divizori a unui numar folosind numerele prime si puterea la care se gasesc ele ( tin sa ii multumesc pe aceasta cale ), insa pentru aceasta am nevoie de un vector in care se afla toate numerle prime mai mici sau egale cu b, ceea ce nu l-am mai intrebat crezand ca stiu sa fac asta..
Am facut algoritmul prin care generez numerele prime , merge , dar depaseste timpu  Brick wall
Cod:
unsigned long prim(unsigned long x)
          {if(x==1)return 0;
           if (x==2) return 1;
           if (x%2==0) return 0;
          for(unsigned long i=3;i<=x/2;i=i+2)
       if(x%i==0)return 0;
          return 1;}    // functia pt aflat numere prime
.............................
p[1]=2;
 k=2;
 for(j=3; j<=b; j=j+2)
    if (prim(j))
      {p[k]=j;
       k++;}  //inserarea in vector a numerelor prime


O sa incerc metoda lui Stefan si revin  Very Happy
« Ultima modificare: Ianuarie 13, 2008, 15:33:29 de către Andrei Panturu » Memorat
skyel
Nu mai tace
*****

Karma: 29
Deconectat Deconectat

Mesaje: 263



Vezi Profilul
« Răspunde #8 : Ianuarie 13, 2008, 16:19:00 »

dar, stii ca fiecare problema de pe infoarena are topic separat in forum, nu? Nu stiu de ce dar am impresia ca te chinui sa faci problema Maxd.
Memorat
wefgef
Nu mai tace
*****

Karma: 1049
Deconectat Deconectat

Mesaje: 3.008


razboinicu' luminii


Vezi Profilul
« Răspunde #9 : Ianuarie 13, 2008, 16:41:56 »

Pentru a rezolva maxd e de ajuns sa parcurgi toate numerele de la a la b si sa numeri cati divizori are fiecare folosind algorimtul postat de Prostu. Nu trebuie sa te chinui in halul asta Smile.
Memorat

omului i-au fost date instinctele pentru a supravietui, nu pentru a fi sclavul lor.
tErMy
Strain


Karma: 1
Deconectat Deconectat

Mesaje: 7



Vezi Profilul
« Răspunde #10 : Ianuarie 13, 2008, 16:54:20 »

dar, stii ca fiecare problema de pe infoarena are topic separat in forum, nu? Nu stiu de ce dar am impresia ca te chinui sa faci problema Maxd.
da ... acea problema incercam sa o rezolv. Imi pare rau daca am gresit facand topicul asta dar sunt nou pe aici si nu am stiut   Embarassed .
am incercat cu algoritmul postat de el dar depaseste timpul la 3 din teste si da rezuktat incorect la celelalte 7.
Asta este sursa.. http://infoarena.ro/job_detail/122745?action=download
Memorat
wefgef
Nu mai tace
*****

Karma: 1049
Deconectat Deconectat

Mesaje: 3.008


razboinicu' luminii


Vezi Profilul
« Răspunde #11 : Ianuarie 13, 2008, 16:59:03 »

Ai acolo if (n%j)... trebuie if (i%j).

Am schimbat asta si am obtinut urmatoarele rezultate: http://infoarena.ro/job_detail/122750

Daca optimizezi putin iei 100.
Memorat

omului i-au fost date instinctele pentru a supravietui, nu pentru a fi sclavul lor.
tErMy
Strain


Karma: 1
Deconectat Deconectat

Mesaje: 7



Vezi Profilul
« Răspunde #12 : Ianuarie 13, 2008, 17:05:50 »

wow ... neatentia   Aha o sa incerc sa optimizez si sa iau 100 puncte.
Multumesc mult tutoror pentru ajutor ! 
Memorat
Pagini: [1]   În sus
  Imprimă  
 
Schimbă forumul:  

Powered by SMF 1.1.19 | SMF © 2006-2013, Simple Machines