Cod sursa(job #3265821)

Utilizator robertcosacCosac Robert-Mihai robertcosac Data 3 ianuarie 2025 16:15:31
Problema Lapte Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.19 kb
#include <iostream>
#include <fstream>
using namespace std;

ifstream fin("primxxl.in");
ofstream fout("primxxl.out");

// x=f1^e1*f2^e2*...*fn^en => Daca exista un factor prim > sqrt(x) atunci el este unic!
//                            In plus, acest factor va avea exponentul 1(daca ar avea
//                            exponentul >= 2, atunci f*f > sqrt(x)*sqrt(x) = x, dar
//                            f^2 divide x, deci este imposibil

// x=f1^e1*...*fn-1^en-1*fn^1 => f1,f2,...fn-1<sqrt(x) si fn>sqrt(x)

const int NRPRIME = 31625;// sqrt(1.000.000.000) ~ 31625

bool ciur[NRPRIME];
int prime[NRPRIME],len=0;

int e2[NRPRIME];//e2[i] = exponentul celui de al i-lea numar prim in descompunerea lui k!
                //e2[i] = [k/prim[i]] + [k/prim[i]^2] + [k/prim[i]^3] +...
int main ()
{
    // aflam numerele prime prin ciurul lui Eratostene
    ciur[0]=ciur[1]=1;
    for(int i=2;i*i<=NRPRIME;i++){
        if(ciur[i]==0){
            for(int j=i*i;j<=NRPRIME;j+=i){
                ciur[j]=1;
            }
        }
    }
    // punem numerele prim intr-un vector
    for(int i=1;i<=NRPRIME;i++){
        if(ciur[i]==0){
            len++;
            prime[len]=i;
        }
    }
    int n,k;
        fin>>n>>k;
    // precalculam valorile lui e2
    for(int i=1;i<=len && prime[i]<=k;i++){
        int f=prime[i];
        while(k/f!=0){
            e2[i]+=k/f;
            f*=prime[i];
        }
    }

    int ans=0;
    for(int i=1;i<=n;i++){
        int x;
        int ok=1;// ok = 1 daca x divide k!
        fin>>x;
        int copy_x=x;
        for(int j=1;j<=len && prime[j]*prime[j]<=copy_x;j++){
            if(x%prime[j]==0){
                int e1=0;
                while(x%prime[j]==0){
                    x/=prime[j];
                    e1++;
                }
                /* Observam ca prin precalcularea valorilor lui e2[i] se
                salveaza timp prin faptul ca acest while nu se mai executa
                pentru ficare x, ci doar o data la inceput
                while(k/f!=0){
                    e2+=k/f;
                    f*=prime[i];
                }
                */
                // Pentru ca x sa divida k! => oricare factor prim al lui x
                // trebuie sa aiba exponentul mai mic decat al lui k!
                if(e1>e2[j]){
                    ok=0;// x  nu divide k! deci ne putem opri
                    break;
                }
            }
        }
        // Dupa ce am trecut prin toti factorii primi mai mici decat sqrt(x)
        // la final o sa ne ramana factorul prim mai mare decat sqrt(x) cu
        // puterea 1 adica x=f, sau x=1(in cazul in care nu avem niciun f>sqrt(x))
        // De asemenea, daca x este numar prim, o sa avem x ul neschimbat in
        // acest moment (x=copy_x), de aceea trebuie sa verificam x>k

        // Pe scurt, in variabila x o sa fie un numar prim la exponentul 1
        // care o sa divida k! doar daca este mai mic decat k
        if(x>k){
            ok=0;
        }

        /*
        if(ok){
            ans++;
        }
        */
        ans+=ok;// secventa de cod echivalenta cu if ul de mai sus
    }
        fout<<ans;
}