Cod sursa(job #1446207)

Utilizator dm1sevenDan Marius dm1seven Data 1 iunie 2015 01:07:37
Problema Suma si numarul divizorilor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.31 kb
/*
 * e_048_suma_divizorilor.cpp
 *
 *  Created on: May 31, 2015
 *      Author: Marius
 */

#include <cmath>
#include <vector>
#include <fstream>
#include <iostream>
using namespace std;

namespace e_048_suma_divizorilor_nms
{
    typedef unsigned long long ull;

    void sieve_primes_up_to(ull MAX_N, int no_of_primes_limit, vector<ull>& primes)
    {
        vector<int> primes_tmp;
        primes_tmp.resize(no_of_primes_limit);

        vector<char> valid;
        valid.resize(MAX_N + 1);
        std::fill(valid.begin(), valid.end(), 1);

        ull prime_upper_limit = (int) sqrt(MAX_N) + 1; //p^2

        int no_of_primes = 0;
        ull nvsp = 1; //next position for searching a valid number
        while (nvsp < prime_upper_limit)
        {
            //select the first valid number in the sequence
            nvsp++;
            while (valid[nvsp] == 0)
                nvsp++;
            ull p = nvsp;

            //insert the number into the list of primes
            primes_tmp[no_of_primes] = p;
            no_of_primes++;

            //invalidate all multiples of p, starting with p^2;
            ull p2 = p * p;
            ull mp = p2;
            while (mp <= MAX_N)
            {
                valid[mp] = 0;
                mp += p;
            }
        }
        
        //the remaining values that are still valid are primes
        for (ull k = nvsp + 1; k <= MAX_N; k++)
            if (valid[k]) primes_tmp[no_of_primes++] = k;

        primes.resize(no_of_primes);
        for (int i = 0; i < no_of_primes; i++)
            primes[i] = primes_tmp[i];
    }

    /// finds the primes dividing n and their exponents
    void calculate_primes_and_powers(ull n, vector<ull>& n_primes, vector<int>& n_powers,
            vector<ull>& primes)
    {

        ull root_n = (ull) sqrt(n);
        int i = 0;
        ull p;
        while ((p = primes[i]) <= root_n)
        {
            int powp = 0;
            while (n % p == 0)
            {
                powp++;
                n /= p;
            }

            if (powp)
            {
                n_powers.push_back(powp);
                n_primes.push_back(p);
            
                root_n = (ull) sqrt(n);
            }
            

            i++;
        }
        
        if (n > 1) //the remaining is prime
        {
            n_primes.push_back(n);
            n_powers.push_back(1);
        }
    }

    void number_and_sum_of_dividers(vector<ull>& n_primes, vector<int>& n_powers,
            int& no_of_dividers, ull& sum_dividers_modulo, ull modulo)
    {
        no_of_dividers = 1;
        sum_dividers_modulo = 1;
        int sz = n_primes.size();
        for (int i = 0; i < sz; i++)
        {
            ull p = n_primes[i];
            int pow_ = n_powers[i];
            no_of_dividers *= pow_ + 1;
            ull p_at_pow1 = 1;
            for (int k = 1; k <= pow_ + 1; k++) p_at_pow1 *= p;
            
            ull p_at_pow1_m1_div_p1 = (p_at_pow1 - 1) / (p - 1);
            sum_dividers_modulo *= p_at_pow1_m1_div_p1;
            sum_dividers_modulo %= modulo;
        }

    }

    void calculate_no_and_sum_dividers(ull n, int& no_of_dividers, ull& sum_divider_modulo,
            ull modulo, vector<ull>& primes)
    {
        vector<ull> n_primes;
        vector<int> n_powers;
        calculate_primes_and_powers(n, n_primes, n_powers, primes);
        number_and_sum_of_dividers(n_primes, n_powers, no_of_dividers, sum_divider_modulo, modulo);
    }
}

int main()
{
    using namespace e_048_suma_divizorilor_nms;
    
    int t;
    
    int modulo = 9973;
    
    //ull MAX_N = 1000000000000;
    ull MAX_N_ROOT = 1000000;
    int no_of_primes_limit = 100000;
    vector<ull> primes;
    sieve_primes_up_to(MAX_N_ROOT, no_of_primes_limit, primes);
    
    ifstream ifs("ssnd.in");
    ofstream ofs("ssnd.out");
    
    ifs >> t;
    for (int k = 1; k <= t; k++)
    {
        ull n;
        ifs >> n;
        int no_of_dividers;
        ull sum_dividers_modulo;
        calculate_no_and_sum_dividers(n, no_of_dividers, sum_dividers_modulo, modulo, primes);
        
        ofs << no_of_dividers << ' ' << sum_dividers_modulo << '\n';
    }
    
    ifs.close();
    ofs.close();
    
    return 0;
}