JATC's math teacher always gives the class some interesting math problems so that they don't get bored. Today the problem is as follows. Given an integer n, you can perform the following operations zero or more times:

  * mul x: multiplies n by x (where x is an arbitrary positive integer). 
  * sqrt: replaces n with √{n} (to apply this operation, √{n} must be an integer). 



You can perform these operations as many times as you like. What is the minimum value of n, that can be achieved and what is the minimum number of operations, to achieve that minimum value?

Apparently, no one in the class knows the answer to this problem, maybe you can help them?

Input

The only line of the input contains a single integer n (1 ≤ n ≤ 10^6) — the initial number.

Output

Print two integers: the minimum integer n that can be achieved using the described operations and the minimum number of operations required.

Examples

Input

20


Output

10 2

Input

5184


Output

6 4

Note

In the first example, you can apply the operation mul 5 to get 100 and then sqrt to get 10.

In the second example, you can first apply sqrt to get 72, then mul 18 to get 1296 and finally two more sqrt and you get 6.

Note, that even if the initial value of n is less or equal 10^6, it can still become greater than 10^6 after applying one or more operations.

import java.io.*;
import java.math.BigInteger;
import java.util.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Collections;
import java.io.InputStreamReader;


public class Main1 {








    public static void main(String[] args) {
            FastScanner in = new FastScanner();
            PrintWriter out = new PrintWriter(System.out);
            int n = in.nextInt() ;

            if (n == 1){
                System.out.println("1 0");
                return;
            }

            seive(n);
            HashMap<Integer , Integer> map = new HashMap<>() ;

            for (int i : list){
                if (i > n)break;
                if (n%i != 0)continue;
                int tt = 0 ;
                while (n%i == 0){
                    tt++ ;
                    n /= i ;
                }
                map.put(i , map.getOrDefault(i , tt-1) + 1) ;
            }
            if (n != 1){
                map.put(n , 1) ;
            }

            int ans = 1 ;
            int cnt =0 ;
            int max = -1 ;

            for (Map.Entry<Integer, Integer> i : map.entrySet() ){
                max = Math.max(max , i.getValue()) ;
                ans *= i.getKey() ;
            }
            int tt = max ;
            if (Integer.highestOneBit(max) != max){
                tt += Integer.highestOneBit(max)*2 - max ;
            }

        for (Map.Entry<Integer, Integer> i : map.entrySet() ){
             cnt += tt - i.getValue() ;
        }
        if (cnt != 0 )cnt = 1 ;
        while (tt%2 == 0){
            cnt++ ;
            tt /=2 ;
        }


        System.out.println((ans) + " " + (cnt));









            out.flush();
            out.close();


    }
    static long gcd(long a, long b) {
        return (b == 0) ? a : gcd(b, a % b);
    }
    static ArrayList<Integer> list = new ArrayList<>();
    static boolean A[] = new boolean[2*90000001];

    static void seive(int n ){
        int maxn = n ;
        //int maxn = 1000000  ;
        A[0] = A[1] = true ;

        for (int i=2 ; i*i<=maxn ; i++){
            if (!A[i]){
                for (int j=i*i ; j<=maxn ; j+= i)
                    A[j] = true ;
            }
        }

        for (int i=2 ; i<=maxn ;i++ )
            if (!A[i])
                list.add(i) ;

    }

    static int findLCA(int a, int b, int par[][], int depth[]) {
        if (depth[a] > depth[b]) {
            a = a ^ b;
            b = a ^ b;
            a = a ^ b;
        }
        int diff = depth[b] - depth[a];
        for (int i = 19; i >= 0; i--) {
            if ((diff & (1 << i)) > 0) {
                b = par[b][i];
            }
        }
        if (a == b)
            return a;
        for (int i = 19; i >= 0; i--) {
            if (par[b][i] != par[a][i]) {
                b = par[b][i];
                a = par[a][i];
            }
        }
        return par[a][0];
    }

    static int gcd(int a, int b) {
        return (b == 0) ? a : gcd(b, a % b);
    }

    static void formArrayForBinaryLifting(int n, int par[][]) {
        for (int j = 1; j < 20; j++) {
            for (int i = 0; i < n; i++) {
                if (par[i][j - 1] == -1)
                    continue;
                par[i][j] = par[par[i][j - 1]][j - 1];
            }
        }
    }


    static void sort(int ar[]) {
        int n = ar.length;
        ArrayList<Integer> a = new ArrayList<>();
        for (int i = 0; i < n; i++)
            a.add(ar[i]);
        Collections.sort(a);
        for (int i = 0; i < n; i++)
            ar[i] = a.get(i);
    }

    static void sort1(long ar[]) {
        int n = ar.length;
        ArrayList<Long> a = new ArrayList<>();
        for (int i = 0; i < n; i++)
            a.add(ar[i]);
        Collections.sort(a);
        for (int i = 0; i < n; i++)
            ar[i] = a.get(i);
    }

    static long ncr(long n, long r, long mod) {
        if (r == 0)
            return 1;
        long val = ncr(n - 1, r - 1, mod);
        val = (n * val) % mod;
        val = (val * modInverse(r, mod)) % mod;
        return val;
    }

    static long fast_pow(long base, long n, long M) {
        if (n == 0)
            return 1;
        if (n == 1)
            return base % M;
        long halfn = fast_pow(base, n / 2, M);
        if (n % 2 == 0)
            return (halfn * halfn) % M;
        else
            return (((halfn * halfn) % M) * base) % M;
    }

    static long modInverse(long n, long M) {
        return fast_pow(n, M - 2, M);
    }


    private static int countDigits(long l) {
        if (l >= 1000000000000000000L) return 19;
        if (l >= 100000000000000000L) return 18;
        if (l >= 10000000000000000L) return 17;
        if (l >= 1000000000000000L) return 16;
        if (l >= 100000000000000L) return 15;
        if (l >= 10000000000000L) return 14;
        if (l >= 1000000000000L) return 13;
        if (l >= 100000000000L) return 12;
        if (l >= 10000000000L) return 11;
        if (l >= 1000000000L) return 10;
        if (l >= 100000000L) return 9;
        if (l >= 10000000L) return 8;
        if (l >= 1000000L) return 7;
        if (l >= 100000L) return 6;
        if (l >= 10000L) return 5;
        if (l >= 1000L) return 4;
        if (l >= 100L) return 3;
        if (l >= 10L) return 2;
        return 1;
    }


    static class FastOutput implements AutoCloseable, Closeable, Appendable {
        private static final int THRESHOLD = 32 << 10;
        private final Writer os;
        private StringBuilder cache = new StringBuilder(THRESHOLD * 2);

        public FastOutput append(CharSequence csq) {
            cache.append(csq);
            return this;
        }

        public FastOutput append(CharSequence csq, int start, int end) {
            cache.append(csq, start, end);
            return this;
        }

        private void afterWrite() {
            if (cache.length() < THRESHOLD) {
                return;
            }
            flush();
        }

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput append(char c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput append(long c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput append(String c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput println() {
            return append(System.lineSeparator());
        }

        public FastOutput flush() {
            try {
                //            boolean success = false;
                //            if (stringBuilderValueField != null) {
                //                try {
                //                    char[] value = (char[]) stringBuilderValueField.get(cache);
                //                    os.write(value, 0, cache.length());
                //                    success = true;
                //                } catch (Exception e) {
                //                }
                //            }
                //            if (!success) {
                os.append(cache);
                //            }
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }


    static class FastScanner {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer("");

        String next() {
            while (!st.hasMoreTokens())
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        int[] readArray(int n) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++) a[i] = nextInt();
            return a;
        }


        long nextLong() {
            return Long.parseLong(next());
        }
    }


}







