Cod sursa(job #2242679)

Utilizator paul_danutDandelion paul_danut Data 19 septembrie 2018 11:37:17
Problema Suma si numarul divizorilor Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 3.21 kb
#include <fstream>
#include <math.h>
//#include <iostream>

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

using namespace std;

constexpr int MAXN = 1000001;


//(a - b) mod p = ((a mod p - b mod p) + p) mod p
//(a / b) mod p = ((a mod p) * (b^(-1) mod p)) mod p
//Where b^(-1) mod p is the modular inverse of b mod p. For p = prime, b^(-1) mod p = b^(p - 2) mod p

void extended_euclid(long long a, long long b, long long &d, long long &x, long long &y)
{
    if( b==0 )
    {
        d = a;
        x = 1;
        y = 0;
    }
    else
    {
        extended_euclid(b, a%b, d, x, y);
        auto x0 =x;
        auto y0 =y;

        y = x0 - ( a / b ) * y0;
        x = y0;
    }
}

long long compute_modular_inverse(long long a, long long b)
{
    long long d = 0, x = 0, y = 0;

    extended_euclid(a, b, d, x, y);

    while(x < 1)
    {
        x += b;
    }

    return x;
}

void initialize(bool filter[])
{
    for(auto i=0; i<MAXN; ++i)
    {
        filter[i] = true;
    }
}

void buildData(bool filter[])
{
    for(auto i=2; i<=MAXN; ++i)
    {
        if(filter[i])
        {
            for(auto j=i+i; j<MAXN; j+=i) //std::cout<<prime_pow<<" " <<prime_pow1 << '\n';
            {
                filter[j] = false;
            }
        }
    }
}

long long power(long long n, long long p, long long mod)
{
    auto r = 1LL;

    while( p != 1 )
    {
        if( p % 2 ==1 )
        r = (n*r) % mod;
        n = (n*n) % mod;
        p = p / 2;
    }

    return ( n * r ) % mod;
}

void computeValues(long long &nr, long long &sum, long long nr_d, long long prime, long long prime_pow = 0)
{
    //auto mi = power(prime-1, 9971, 9973);                 ///For p = prime, b^(-1) mod p = b^(p - 2) mod p
    auto mi = compute_modular_inverse(prime-1, 9973);
    if(prime_pow == 0)
    {
        prime_pow = power(prime, nr_d + 1, 9973) - 1;
    }
    else
    {
        prime_pow = (prime_pow-1) % 9973;
    }

    sum = (sum * prime_pow * mi) % 9973;
    nr *= nr_d + 1;
}

bool filter[MAXN];


int main()
{
    int t=0;

    long long x=0;
    long long int sum = 0;
    long long int nr = 0;

    initialize(filter);
    buildData(filter);

    f>>t;
    while(t > 0)
    {
        f >> x;
        sum = 1;
        nr = 1;

        if(x < MAXN && filter[x])
        {
            ++nr;
            sum = (sum + x) % 9973;
        }
        else
        {
            for(auto i = 2; i < MAXN; ++i)
            {
                if(filter[i])
                {
                    auto nr_d = 0;
                    auto v = 1;
                    while( x % (v*i) == 0 )
                    {
                        ++ nr_d;
                        v *= i;
                    }
                    x /= v;
                    v *= i;

                    if(nr_d > 0)
                    {
                        computeValues(nr, sum, nr_d, i, v);
                    }
                }
            }
            if(x >= MAXN)
            {
                ++nr;
                computeValues(nr, sum, 1, x);
            }
        }

        g << nr << ' ' << sum <<'\n';

        --t;
    }
}