18414 afișări Mititelu Ana Mirela (AnaMititelu) 29.08.2019
www.pbinfo.ro

Există o serie de probleme pentru care rezolvarea lor se rezumă la aflarea exponentului unui număr dat k,exp(k) , într-un produs factorial (n!), fără a calcula acel produs.
O metodă naivă ar fi căutarea multiplior lui k mai mici sau egali cu n și de câte ori de divid acestia cu k.
Exemplu:
n=75,k=7
n!=123456714212835424956637075
n!=117273747576777879771075 exp(7)=11

O soluție ar fi parcurgerea intervalului [k,n]cu pasul k și contorizarea multiplilor.

C++
______________________________
exp=0 for (int i=k;i<=n;i+=k) { int x=i; while(x%k==0) {exp++;x/=k;} } cout<<exp;
___________________________
Termenul dominant este T(n) ->n/k (algoritm linear).
O altă soluție ar fi folosirea unei formule de calcul a exponentului lui k în n! notat expn!(k), numită formula lui Legendre.
Dacă numărul k este prim expn!(k)=[nk]+[nk2]+[nk3]+
Exemplu:n=75,k=7
exp75!(7)=[757]+[7549]+[75343]=10+1+0=11
Se poate deduce că după un anumit număr de pași raportul va deveni subunitar ceea ce determină că suma va avea un număr finit de termeni. Pornind de la această relație, valoarea acelui exponent se poate calcula însumând câturile împărțirilor succesive.

Implementarea C++.
________________________________________
exp=0 while(n>=k) { n=n/k; exp+=n; }
________________________________________
Termenul dominant este T(n) ->log(n) (algoritm logaritmic)
Dacă numărul k este un număr compus și în descompunerea în factori primi se obține produsul k=d1e1d2e2dlel unde d1,d2,,dl sunt factorii primi iar e1,e2,,el exponenții acestora, vom folosi relațiile matematice (1) și (2), unde:
expn!(de)=[expn!(d)e](1)
expn!(k)=min{expn!(d1e1),expn!(d2e2),expn!(d3e3),expn!(dlel)}(2)

Exemplu:
n=75,k=12
12=223
exp75!(22)=[exp75!(2)2]=([752]+[754]+[758]+[7516]+[7532]+[7564]+[75128])/2=(37+28+4+1+0)/2=35.
exp75!(3)=[753]+[759]+[7527]+[7581]=25+8+2+0=35.
În concluzie,
exp75!(12)=min(35,35)=35

Implementare C++
________________________________________
int a,b,divi[100],puterea[100],poz,minim; int putere(int n,int p) { int x=0; while(n>p) { x+=n/p; n=n/p; } return x; } int main() { f>>b>>a; int d=2; while(d*d<=a) { if(a%d==0) { divi[++poz]=d; int c=0; while(a%d==0) { a/=d puterea[poz]++; }} d++; } if(a!=1) { divi[++poz]=a; puterea[poz]=1; } minim=1000000; for(int i=1;i<=poz;i++) { puterea[i]=putere(b,divi[i])/puterea[i]; if(minim>puterea[i]) minim=puterea[i]; } g << minim; return 0; }
________________________________________


Probleme ataşate

Nr. Problema Clasa Dificultate Operații I/O
1 #1826 - ZeroF 10 ușoară consola
2 #0440 - FactZero1 9 medie consola
3 #0439 - FactZero 9 ușoară consola
4 #1780 - Fractie 9 medie consola
18414 afișări Mititelu Ana Mirela (AnaMititelu) 29.08.2019
www.pbinfo.ro
Du-te sus!