Cod sursa(job #731612)

Utilizator alex_unixPetenchea Alexandru alex_unix Data 8 aprilie 2012 15:52:24
Problema Suma divizorilor Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.21 kb

#include <fstream>
#include <cmath>

const unsigned short MOD(9901);

inline unsigned int E (unsigned short *&p1, unsigned int *&p2)
{
    unsigned long long power(*p2 + 1),base(*p1 % MOD),aux1(1);
    for (unsigned int bit(0x01) ; bit <= power ; bit <<= 1)
    {
        if (power & bit)
        {
            aux1 *= base;
            aux1 %= MOD;
        }
        base *= base;
        base %= MOD;
    }
    --aux1;
    aux1 += MOD;
    aux1 %= MOD;
    if (!aux1)
        return power % MOD;
    unsigned long long aux2(1);
    power = MOD - 2;
    base = *p1 - 1;
    for (unsigned int bit(0x01) ; bit <= power ; bit <<= 1)
    {
        if (power & bit)
        {
            aux2 *= base;
            aux2 %= MOD;
        }
        base *= base;
        base %= MOD;
    }
    return aux1 * aux2 % MOD;
}

int main (void)
{
    unsigned int a,b;
    std::ifstream input("sumdiv.in");
    input >> a >> b;
    input.close();
    unsigned short primes [15],*prim_ptr(primes);
    unsigned int powers [15],*pow_ptr(powers),aux(a);
    if (!(a && b))
    {
        std::ofstream output("sumdiv.out");
        output << (a ? '1' : '0') << '\n';
        output.close();
        return 0;
    }
    if (!(a % 2))
    {
        *prim_ptr = 2;
        ++prim_ptr;
        *pow_ptr = 1;
        a >>= 1;
        while (!(a % 2))
        {
            a >>= 1;
            ++*pow_ptr;
        }
        *pow_ptr *= b;
        ++pow_ptr;
    }
    for (unsigned short i(3), limit(std::sqrt(aux)) ; i <= limit ; i += 2)
    {
        if (!(a % i))
        {
            *prim_ptr = i;
            ++prim_ptr;
            *pow_ptr = 1;
            a /= i;
            while (!(a % i))
            {
                a /= i;
                ++*pow_ptr;
            }
            *pow_ptr *= b;
            ++pow_ptr;
        }
    }
    if (a != 1)
    {
        *prim_ptr = a;
        *pow_ptr = 1;
        ++prim_ptr;
        ++pow_ptr;
    }
    unsigned long long result(1);
    unsigned short *p1(primes);
    unsigned int *p2(powers);
    while (p1 < prim_ptr)
    {
        result *= E(p1,p2);
        result %= MOD;
        ++p1;
        ++p2;
    }
    std::ofstream output("sumdiv.out");
    output << result << '\n';
    output.close();
    return 0;
}