Pagini recente » Istoria paginii preoni-2008/runda-1/5-8 | Monitorul de evaluare | Istoria paginii utilizator/zupermi | Monitorul de evaluare | Cod sursa (job #869764)
Cod sursa(job #869764)
//Solutia se bazeaza pe cateva observatii matematice si pe metoda programarii dinamice, astfel problema este rezolvata in O(r)
#include <fstream>
using namespace std;
//In acesti vectori se retine cati factori de 2,3 sau 5 sunt in descompunerea numarului i, indice al vectorului
unsigned short int fact2[5000001];
unsigned short int fact3[5000001];
unsigned short int fact5[5000001];
int main()
{
//Deschiderea fisierelor de intrare si iesire
ifstream fin("pascal.in");
ofstream fout("pascal.out");
//d si r din enuntul problemei
int d,r;
//i - contor
int i;
//Citim datele problemei
fin>>r;
fin>>d;
//Construim vectorii prin programare dinamica
for(i=2;i<=r;i++)
{
//Numai numerele divizibile cu 2,3 sau 5 trebuie calculate, restul sunt 0
if(i%2==0)
fact2[i]=fact2[i/2]+1;
if(i%3==0)
fact3[i]=fact3[i/3]+1;
if(i%5==0)
fact5[i]=fact5[i/5]+1;
}
//Aici incepe solutia propriu-zisa, ea se bazeaza pe observatia ca C(n,k)=C(n,k-1)*((n-k+1)/k), deci numarul de
//factori de d vor fi F(n,k)=F(n,k-1)+factd[n-k+1]-factd[k]. Acest F(n,k) il vom calcula folosind insa numai fact2,
//fact3 si fact5, iar in n2,n3 si n5 tinem numarul curent de factori de 2,3 si 5.
int n2=0,n3=0,n5=0;
//In sol tinem cate numere de pe randul r sunt divizibile cu d
int sol=0;
//Programul poate fi imbunatatit pentru a lucra numai pana la mijlocul randului, acesta fiind simetric, insa nu e nevoie
//de aceasta imbunatatire pentru 100 puncte. In folosirii imbunatatirii acesteia trebuie luat in calcul si faptul ca elementul din
//mijloc nu are simetric in cazul unui numar impar de elemente
for(i=1;i<r;i++)
{
//Actualizam n-urile
n2=n2-fact2[i]+fact2[r-i+1];
n3=n3-fact3[i]+fact3[r-i+1];
n5=n5-fact5[i]+fact5[r-i+1];
//Daca d este 2,3 sau 5 atunci pentru nd pozitiv crestem solutiile, acest lucru insemnand ca acel element se imparte la d
if(d==2 && n2>0)
{
sol++;
}
else if(d==3 && n3>0)
{
sol++;
}
else if(d==4 && n2>1) //Pentru d=4, trebuie sa avem minim 2 factori de 2 pentru ca elementul sa fie divizibil cu 4
{
sol++;
}
else if(d==5 && n5>0)
{
sol++;
}
else if(d==6 && n2>0 && n3>0) //Pentru d=6, trebuie sa avem minim un factor de 2 si unul de 3
{
sol++;
}
}
//Afisam numarul de elemente de pe randul r divizibile cu d
fout<<sol<<'\n';
//Inchiderea fisierelor de intrare si iesire
fin.close();
fout.close();
return 0;
}