Cod sursa(job #778827)

Utilizator alex_unixPetenchea Alexandru alex_unix Data 15 august 2012 22:16:46
Problema Suma si numarul divizorilor Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 2.22 kb

#include <cstdio>

const unsigned int LIMIT(1000001);
const unsigned int MAX_PRIMES(78497);

bool v [LIMIT];
unsigned int primes [MAX_PRIMES];

inline void Eratosthenes (void)
{
	bool *iterator(v + 3), *end(v + LIMIT), *multiple;
	unsigned int *add_prime(primes), number;
	do
	{
		if (!*iterator)
		{
			*add_prime = number = iterator - v;
			++add_prime;
			for (number <<= 1, multiple = iterator + number ; multiple < end ; multiple += number)
				*multiple = true;
		}
		iterator += 2;
	}
	while (iterator < end);
}

inline unsigned int BabylonianMethod (long double n)
{
	static const unsigned char LOOP(23);
	long double guess(1);
	for (unsigned char counter(0) ; counter < LOOP ; ++counter)
		guess = (guess + n / guess) / 2;
	return guess;
}

inline unsigned long long power_raise (unsigned long long base, unsigned int exponent)
{
	static const unsigned int MODULO(9973);
	unsigned long long result(1);
	for (unsigned int bit(0x01) ; bit <= exponent ; bit <<= 1)
	{
		if (bit & exponent)
		{
			result *= base;
			result %= MODULO;
		}
		base *= base;
		base %= MODULO;
	}
	return result;
}

int main (void)
{
	Eratosthenes();
	const unsigned int MODULO(9973);
	unsigned int t;
	std::freopen("ssnd.in","r",stdin);
	std::scanf("%u",&t);
	std::freopen("ssnd.out","w",stdout);
	unsigned int *iterator, sqrt, divisors, base, exponent, sum;
	unsigned long long n, *n_ptr(&n);
	do
	{
		std::scanf("%llu",n_ptr);
		sqrt = BabylonianMethod(n);
		divisors = 1;
		sum = 1;
		if (!(n % 2))
		{
			exponent = 1;
			n >>= 1;
			while (!(n % 2))
			{
				n >>= 1;
				++exponent;
			}
			divisors *= (exponent + 1);
			sum = (2 << exponent) - 1;
			sum %= MODULO;
		}
		iterator = primes;
		while (*iterator <= sqrt && n != 1)
		{
			base = *iterator;
			if (!(n % base))
			{
				exponent = 1;
				n /= base;
				while (!(n % base))
				{
					n /= base;
					++exponent;
				}
				divisors *= (exponent + 1);
				sum *= (power_raise(base,exponent + 1) - 1) / (base - 1);
				sum %= MODULO;
			}
			++iterator;
		}
		if (n != 1)
		{
			base = n;
			divisors <<= 1;
			sum *= ((static_cast<unsigned long long>(base) * base % MODULO) - 1) / (base - 1);
			sum %= MODULO;
		}
		std::printf("%u %u\n",divisors,sum);
		--t;
	}
	while (t);
	std::fclose(stdin);
	std::fclose(stdout);
}