Totient Until The End
Difficulty: Hard

Saito promises to stay by Louise's side until the end. Louise wants to test the strength of Saito's promise by having him calculate the *totient* until the end.

The *totient of $N$*, written as $\phi(N)$, is the number of integers $K$ such that $1 \le K \le N$ and $\gcd(K,N) = 1$. It is clear that when the function $\phi$ is iterated starting from $N$, we will eventually reach $1$ (which we'll call *the end*).

Given $N$, Louise asks Saito to find the number of iterations of $\phi$ that can be done until the end (i.e. the number of iterations until we reach $1$). Since $N$ is very large, it will be given in the form $N = a^b c^d e^f g^h$.

If Saito is unable to do this, he will receive ten thousand lashes. Please help Saito accomplish this task and prove his worth to Louise!

**Input Format**  
The first line of input contains a single integer, $T$, which is the number of test cases. The following lines contain the test cases.

Each test case consists of one line containing eight integers, $a$, $b$, $c$, $d$, $e$, $f$, $g$, and $h$.

**Output Format**  
For each test case output a single line containing the answer.

**Constraints**  
$1 \le T \le 5\times 10^4$  
$1 \le a, b, c, d, e, f, g, h \le 2\times 10^6$  

**Sample Input**  

    2
    2 2 3 1 3 1 6 1
    1 1 1 1 1 1 1 1

**Sample Output**  

    6
    0
    
**Explanation**  
In the first test case, $N = 2^2 3^1 3^1 6^1 = 216$, so iterating $\phi$, we get:  
$$216 \rightarrow 72 \rightarrow 24 \rightarrow 8 \rightarrow 4 \rightarrow 2 \rightarrow 1$$
Therefore, $6$ iterations are needed to reach $1$.

In the second test case, since $N = 1$ already, we need $0$ iterations to reach $1$.

Input Format:

Output Format:

Sample Input:

Sample Output:

Python 3 starter code:


Reference solution (C++):
    #include <stdio.h>
    #define N 2000000
    #define alok(n,t) ((t*)malloc((n)*sizeof(t)))
    #include <algorithm>
    using namespace std;

    int pf[N+1];
    int ex[N+1];
    int rm[N+1];
    int *n = alok(1111, int);
    int *m = alok(1111, int);
    int pi[N+1];
    int pis[11111];
    int tk[N+1];
    int pic, cas;
    void collect(int n) {
        while (!(n & 1)) n >>= 1;
        while (n > 1) {
            int p = pf[n];
            n = rm[n];
            if (tk[p] != cas) {
                tk[p] = cas;
                pis[pic++] = p;
                collect(p-1);
            }
        }
    }
    int main() {
        for (int i = 0; i <= N; i++) {
            pf[i] = i;
            ex[i] = rm[i] = tk[i] = 0;
        }
        for (int n = 2; n <= N; n++) {
            if (pf[n] == n) {
                for (int j = n; j <= N; j += n) {
                    pf[j] = n;
                }
            }
            rm[n] = n / pf[n];
            ex[n] = 1;
            if (rm[n] % pf[n] == 0) {
                ex[n] += ex[rm[n]];
                rm[n] = rm[rm[n]];
            }
        }

        int z;
        scanf("%d", &z);
        for (cas = 1; cas <= z; cas++) {
            int a, b, c, d, e, f, g, h;
            scanf("%d%d%d%d%d%d%d%d", &a, &b, &c, &d, &e, &f, &g, &h);
            pic = 0;
            collect(a);
            collect(c);
            collect(e);
            collect(g);
            if (a > 1 || c > 1 || e > 1 || g > 1) pis[pic++] = 2;
            if (pic == 0) {
                printf("0\n");
                continue;
            }
            sort(pis, pis + pic);
            for (int i = 0; i < pic; i++) {
                pi[pis[i]] = i;
                n[i] = 0;
            }

            for (; a > 1; a = rm[a]) n[pi[pf[a]]] += ex[a]*b;
            for (; c > 1; c = rm[c]) n[pi[pf[c]]] += ex[c]*d;
            for (; e > 1; e = rm[e]) n[pi[pf[e]]] += ex[e]*f;
            for (; g > 1; g = rm[g]) n[pi[pf[g]]] += ex[g]*h;
            c = 0;
            while (1) {
                while (~--pic && !n[pic]);
                if (!++pic) break;

                for (int i = 0; i < pic; i++) {
                    m[i] = 0;
                }

                for (int i = 0; i < pic; i++) {
                    int e = n[i];
                    if (!e) continue;
                    if (e > 1) m[i] += e-1;

                    for (int f = pis[i]-1; f > 1; f = rm[f]) {
                        m[pi[pf[f]]] += ex[f];
                    }
                }

                int eq = 1;
                for (int i = 0; i < pic; i++) {
                    if (!m[i]^!n[i]) {
                        eq = 0;
                        break;
                    }
                }

                if (eq) {
                    int r = 2000000000;
                    for (int i = 0; i < pic; i++) {
                        int e = n[i];
                        if (!e) continue;
                        if (e > m[i]) {
                            if (r > e) r = e;
                        }
                    }
                    for (int i = 0; i < pic; i++) {
                        int e = n[i];
                        if (!e) continue;
                        n[i] = e + (m[i] - e) * r;
                    }
                    c += r;
                } else {
                    int *temp = n; n = m, m = temp;
                    c++;
                }
            }
            printf("%d\n", c);
        }
    }