Pagini recente » Cod sursa (job #1202644) | Cod sursa (job #1446206)
/*
* 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++)
{
int 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;
}