Cod sursa(job #2725662)

Utilizator flibiaVisanu Cristian flibia Data 19 martie 2021 14:30:49
Problema Suma si numarul divizorilor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.85 kb
#include <bits/stdc++.h>
#define ll long long 
#define MOD 9973
 
using namespace std;
 
ifstream in("ssnd.in");
ofstream out("ssnd.out");
 
int t; 
ll n;
 
ll fast_pow(ll n, ll p) {
    ll ans = 1;
    int lim = 64 - __builtin_clzll(p);
 
    for (int i = 0; i <= lim; i++) {
        if (p & (1ll << i)) {
            ans = (ans * n) % MOD; 
        }
 
        n = (n * n) % MOD;
    }
 
    return ans; 
}
 
ll inverse(ll n) {
    return fast_pow(n, MOD - 2);
}

namespace sieve {
    vector<int> primes;
    vector<int> lp;
    const int limit = 1e6; // change accordingly
    int primesCount = 0;

    // classic sieve
    void build() {
        bitset<limit + 1> marked;
    
        for (int i = 2; i <= limit; i++) {
            if (!marked[i]) {
                primes.push_back(i);
                primesCount++;
    
                for (int j = i + i; j <= limit; j += i) {
                    marked[j] = 1;
                }
            }
        }
    }

    // linear sieve that also computes lp[i] = least prime factor of i
    void build_linear() {
        lp = vector<int>(limit + 1);
    
        for (int i = 2; i <= limit; i++) {
            if (!lp[i]) {
                lp[i] = i;
                primes.push_back(i);
                primesCount++;
            }
    
            for (int j = 0; j < (int) primes.size() && primes[j] <= lp[i] && primes[j] * i <= limit; j++) {
                lp[i * primes[j]] = primes[j];
            }
        }
    }
    
    // should be used for numbers up to limit, uses lp vector
    template<typename T> 
    vector<pair<T, int> > decomposeWithLP(T n) {
        vector<pair<T, int> > decomposition;
        int pv = -1;
        
        while (n > 1) {
            if (lp[n] != pv) {
                pv = lp[n];
                decomposition.push_back({lp[n], 1});
            } else {
                decomposition.back().second++;
            }
            
            n /= lp[n];
        }
    
        return decomposition;
    }

    // can be used for numbers up to limit * limit
    template<typename T> 
    vector<pair<T, int> > decompose(T n) {
        vector<pair<T, int> > ans;
        
        for (auto i : primes) {
            if (1ll * i * i > n) {
                break;
            }
    
            if (n % i) {
                continue;
            }
    
            int count = 0;
            while (n % i == 0) {
                count++;
                n /= i;
            }
    
            ans.push_back({i, count});
        }
    
        if (n > 1) {
            ans.push_back({n, 1ll});
        }
    
        return ans;
    }
    
    // generates all divisors of a number (into param::factors) given its prime factors decomposition
    template<typename T>
    void genDivisors(const vector<pair<T, int> > &decomposition, vector<T> &factors, T factor = 1, int pos = 0) {
        if (pos == (int) decomposition.size()) {
            factors.push_back(factor);
            return;
        }
    
        for (int i = 0; i <= decomposition[pos].second; i++) {
            factorize(decomposition, factors, factor, pos + 1);
            factor *= decomposition[pos].first;
        }
    }
}

using namespace sieve;
 
void solve(const vector<int> &primes) {
    in >> n;
 
    ll div_sum = 1, div_count = 1;
    // auto decomp = decompose(n);
    vector<pair<ll, int> > decomp;
    if (n <= 1e6) {
        decomp = decomposeWithLP(n);
    } else {
        decomp = decompose(n);
    }

    for (auto it : decomp) {
        ll div = it.first, div_pow = it.second;
        div = div % MOD; 
 
        div_count = div_count * (div_pow + 1) % MOD;
 
        div_sum = (div_sum * (fast_pow(div, div_pow + 1) - 1)) % MOD;
        div_sum = (div_sum * inverse(div - 1)) % MOD;
    }

    out << div_count << ' ' << div_sum << '\n';
}
 
int main() {
    build_linear();

    in >> t;
    while (t--) {
        solve(primes);
    }
    
    return 0;
}