Cod sursa(job #3256012)

Utilizator dvviddManciu David dvvidd Data 12 noiembrie 2024 22:31:01
Problema Suma si numarul divizorilor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.11 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>

using namespace std;

ifstream f("ssnd.in");
ofstream g("ssnd.out");

// Generăm toți factorii primi până la un anumit număr folosind ciurul lui Eratostene
vector<long> generare_primi(long limita) {
    vector<bool> este_prim(limita + 1, true);
    vector<long> primi;
    este_prim[0] = este_prim[1] = false;
    for (long i = 2; i <= limita; i++) {
        if (este_prim[i]) {
            primi.push_back(i);
            for (long j = i * i; j <= limita; j += i) {
                este_prim[j] = false;
            }
        }
    }
    return primi;
}

// Funcția principală care calculează numărul și suma divizorilor folosind descompunerea în factori primi
void calculeaza_divizori(long n, const vector<long>& primi) {
    long nr_divizori = 1;
    long suma_divizori = 1;
    long original_n = n;

    for (long p : primi) {
        if (p * p > n) break;
        if (n % p == 0) {
            int putere = 0;
            long putere_p = 1;
            while (n % p == 0) {
                n /= p;
                putere++;
                putere_p *= p;
            }
            nr_divizori *= (putere + 1);

            // Calculăm contribuția lui p la suma divizorilor
            long suma_factor = (putere_p * p - 1) / (p - 1);
            suma_divizori *= suma_factor;
        }
    }

    // Dacă n este un număr prim mai mare decât \sqrt{original_n}
    if (n > 1) {
        nr_divizori *= 2;
        suma_divizori *= (n + 1);
    }

    // Scriem rezultatul în fișier
    g << nr_divizori << " " << (suma_divizori % 9973) << endl;
}

int main() {
    int t;
    f >> t;
    vector<long> numere(t);
    long max_n = 0;

    for (int i = 0; i < t; i++) {
        f >> numere[i];
        max_n = max(max_n, numere[i]);
    }

    // Generăm toți factorii primi până la sqrt(max_n)
    long limita = sqrt(max_n) + 1;
    vector<long> primi = generare_primi(limita);

    for (int i = 0; i < t; i++) {
        calculeaza_divizori(numere[i], primi);
    }

    return 0;
}