Challenge: Divisor Exploration 3

Subdomeniu: Number Theory (number-theory)

Scor cont: 55.0 / 55

Submission status: Accepted

Submission score: 1.0

Submission ID: 464753844

Limbaj: cpp14

Link challenge: https://www.hackerrank.com/challenges/divisor-exploration-3/problem

Cerinta

You are given $q$ queries where each query is in the form of three integers, $m$, $a$ and $d$, such that:
$$n = \prod\limits_{i = 1}^{m} p_i^{a+i} \text{, where } p_i \text{ is the } i^{th} \text{ prime.}$$  

Using this value of $n$ along with the given $d$, create a tree $T$ as follows :-  

+ The value $n$ is the root of the tree.  
+ A node is expanded such that all it's divisors are it's children.  
+ Continue expanding till the tree has depth $d$.  

For example, if $n = 6$ and $d = 2$, then the tree will look like the following:

![image](https://s3.amazonaws.com/hr-assets/0/1495184919-545b96c7df-1443016945-9de543f952-DivisorTree.jpg)

Once the tree is built, we create another tree $U$ as follows :- 

+ Every leaf node $x \in T$, is transformed to $\phi(x)$. Here $\phi()$ is the totient function.   
+ Every non-leaf node is equal to the sum of the values of it's children.  

From our previous example tree, after constructing a new tree, we get the following tree.  

![image](https://s3.amazonaws.com/hr-assets/0/1495184934-4e72171d3d-1443017061-c3e2051775-DivisorTreewithSpecialValue.jpg)

Print the value at the root of tree $U$ after taking modulo with $(10^9+7)$.

Input Format

The first line of the input contains a single integer $q$ ( $q \leq 50$ ).  
Following $q$ lines contain three integers given by $m$, $a$ and $d$.

Output Format

For each case, print the value at the root of tree $U$ modulo $(10^9+7)$.

Constraints

**For $30\%$ points:**   

+ $1 \leq m \leq 100$
+ $0 \leq a \leq 100$
+ $1 \leq d \leq 100$  

**For Full Points:**  

+ $1 \leq m \leq 1000$
+ $0 \leq a \leq 1000$
+ $1 \leq d \leq 1000$

Cod sursa

#include <bits/stdc++.h>
using namespace std;

static const long long MOD = 1000000007LL;

long long mod_pow(long long a, long long e) {
    long long r = 1 % MOD;
    a %= MOD;
    while (e > 0) {
        if (e & 1) r = (r * a) % MOD;
        a = (a * a) % MOD;
        e >>= 1;
    }
    return r;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int q;
    if (!(cin >> q)) return 0;

    vector<tuple<int,int,int>> qs(q);
    int max_m = 0, max_a = 0, max_d = 0;
    for (int i = 0; i < q; ++i) {
        int m, a, d;
        cin >> m >> a >> d;
        qs[i] = {m, a, d};
        max_m = max(max_m, m);
        max_a = max(max_a, a);
        max_d = max(max_d, d);
    }

    // First max_m primes.
    int LIM = 100000;
    while (true) {
        vector<bool> is_prime(LIM + 1, true);
        is_prime[0] = is_prime[1] = false;
        for (int i = 2; 1LL * i * i <= LIM; ++i) {
            if (!is_prime[i]) continue;
            for (int j = i * i; j <= LIM; j += i) is_prime[j] = false;
        }
        vector<int> primes;
        primes.reserve(max_m);
        for (int i = 2; i <= LIM && (int)primes.size() < max_m; ++i) {
            if (is_prime[i]) primes.push_back(i);
        }
        if ((int)primes.size() == max_m) {
            // Prepare factorials for combinations up to (max_e + max_d).
            int max_e = max_a + max_m;
            int max_n = max_e + max_d + 5;

            vector<long long> fact(max_n + 1, 1), inv_fact(max_n + 1, 1);
            for (int i = 1; i <= max_n; ++i) fact[i] = fact[i - 1] * i % MOD;
            inv_fact[max_n] = mod_pow(fact[max_n], MOD - 2);
            for (int i = max_n; i >= 1; --i) inv_fact[i - 1] = inv_fact[i] * i % MOD;

            auto nCr = [&](int n, int r) -> long long {
                if (r < 0 || r > n) return 0;
                return fact[n] * inv_fact[r] % MOD * inv_fact[n - r] % MOD;
            };

            for (auto [m, a, d] : qs) {
                long long ans = 1;

                for (int i = 1; i <= m; ++i) {
                    long long p = primes[i - 1];
                    int e = a + i;

                    long long g;
                    if (d == 1) {
                        g = mod_pow(p, e);
                    } else {
                        // G_d(e) = sum_{t=0..e} C(e-t + d-2, d-2) * p^t
                        long long pw = 1;
                        g = 0;
                        for (int t = 0; t <= e; ++t) {
                            int nn = (e - t) + (d - 2);
                            long long c = nCr(nn, d - 2);
                            g = (g + c * pw) % MOD;
                            pw = (pw * p) % MOD;
                        }
                    }

                    ans = (ans * g) % MOD;
                }

                cout << ans << '\n';
            }
            return 0;
        }
        LIM *= 2;
    }
}
HackerRank Number Theory – Divisor Exploration 3