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 <unordered_map>

    using namespace std;

    unordered_map<int,int> d,updList;
    unordered_map<int,int>::iterator it;
    int p[2000001];
    int toAdd[200],toDelete[200];

    inline void addToDict(int key,int value)
    {
        value+=updList[key];
        if(!value)updList.erase(key);
        else updList[key]=value;
    }

    inline void addPrime(int key,int value)
    {
        addToDict(key,-value);
        --key;
        while(p[key])
        {
            addToDict(p[key],value);
            key/=p[key];
        }
    }

    int main()
    {
        int T,i,n,ok;
        int mi,c,a,j;
        int ans,ts,m,k;
        for(i=2;i*i<=2000000;i++)
            if(!p[i])
            {
                p[i]=i;
                for(j=i*i;j<=2000000;j+=i)
                    p[j]=i;
            }
        for(;i<=2000000;i++)
            if(!p[i])
                p[i]=i;
        scanf("%d",&T);
        for(ts=0;ts<T;ts++)
        {
            for(i=0;i<4;i++)
            {
                scanf("%d%d",&n,&a);
                while(p[n])
                {
                    d[p[n]]+=a;
                    n/=p[n];
                }
            }
            updList.clear();
            for(it=d.begin();it!=d.end();++it)
                addPrime(it->first,1);
            ans=0;
            while(!d.empty())
            {
                ok=0;
                mi=1999999999;
                for(it=updList.begin();it!=updList.end();++it)
                    if(!d[it->first])
                    {
                        ok=1;
                        break;
                    }
                    else if(it->second<0)
                        mi=min(mi,d[it->first]);
                if(ok)mi=1;
                ans+=mi;
                m=k=0;
                for(it=updList.begin();it!=updList.end();++it)
                {
                    n=d[it->first];
                    if(!n)
                    {
                        toAdd[m++]=it->first;
                        d[it->first]=it->second*mi;
                        continue;
                    }
                    n+=it->second*mi;
                    if(!n)
                    {
                        d.erase(it->first);
                        toDelete[k++]=it->first;
                    }
                    else
                        d[it->first]=n;
                }
                for(i=0;i<m;i++)
                    addPrime(toAdd[i],1);
                for(i=0;i<k;i++)
                    addPrime(toDelete[i],-1);
            }
            printf("%d\n",ans);
        }
        return 0;
    }