Problem:
Score : 400 points

Problem Statement

Given is a positive integer N. Consider repeatedly applying the operation below on N:

First, choose a positive integer z satisfying all of the conditions below:

z can be represented as z=p^e, where p is a prime number and e is a positive integer;

z divides N;

z is different from all integers chosen in previous operations.

Then, replace N with N/z.

Find the maximum number of times the operation can be applied.

Constraints

All values in input are integers.

1 \leq N \leq 10^{12}

Input

Input is given from Standard Input in the following format:

N

Output

Print the maximum number of times the operation can be applied.

Sample Input 1

24

Sample Output 1

3

We can apply the operation three times by, for example, making the following choices:

Choose z=2 (=2^1). (Now we have N=12.)

Choose z=3 (=3^1). (Now we have N=4.)

Choose z=4 (=2^2). (Now we have N=1.)

Sample Input 2

1

Sample Output 2

0

We cannot apply the operation at all.

Sample Input 3

64

Sample Output 3

3

We can apply the operation three times by, for example, making the following choices:

Choose z=2 (=2^1). (Now we have N=32.)

Choose z=4 (=2^2). (Now we have N=8.)

Choose z=8 (=2^3). (Now we have N=1.)

Sample Input 4

1000000007

Sample Output 4

1

We can apply the operation once by, for example, making the following choice:

z=1000000007 (=1000000007^1). (Now we have N=1.)

Sample Input 5

997764507000

Sample Output 5

7

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Numerics;

namespace ABC169
{
    using static Ex;
    public class Solve
    {
        public static void Main(string[] args)
        {
            new ABC_D();
        }
    }
    public class ABC_A
    {
        int a, b;
        public ABC_A()
        {
            (a, b) = ReadValue<int, int>();
            var c = (a * b);
            c.Cw();
        }
    }
    public class ABC_B
    {
        public ABC_B()
        {
            long n = ReadLong;
            long[] arr = ReadLongArray();
            if (arr.Any(v => v == 0))
            {
                0.Cw();
                return;
            }

            long ans = 1;
            foreach (var v in arr)
            {
                if (ans > long.MaxValue / v)
                {
                    (-1).Cw();
                    return;
                }
                if (ans * v > 1000000000000000000)
                {
                    (-1).Cw();
                    return;
                }
                ans *= v;
            }
            ans.Cw();
        }
    }
    public class ABC_C
    {
        long a;
        double b;
        public ABC_C()
        {
            (a, b) = ReadValue<long, double>();
            long bl = (long)(b * 100.0);
            var c = (a * bl).ToString();

            if (a == 0 || bl == 0 || c.Length <= 2)
            {
                0.Cw();
                return;
            }
            c.Substring(0, c.Length - 2).Cw();
        }
    }
    public class ABC_D
    {
        long n;
        public ABC_D()
        {
            n = ReadLong;

            long ans = 0;
            var v = prime_factorize(n);
            foreach (var x in v)
            {
                //$"{x.Item1} {x.Item2}".Cw();

                var ex = x.Item2;
                long i = 1;
                for (; i <= ex; i++)
                {
                    //$" ;{i} {ex}".Cw();
                    ex -= i;
                    if (ex < 0)
                    {
                        i--;
                        break;
                    }
                    if (ex == 0 || i >= ex)
                    {
                        break;
                    }
                }
                ans += i;
            }

            ans.Cw();
        }

        List<(long, long)> prime_factorize(long N)
        {
            var res = new List<(long, long)>();
            for (long a = 2; a * a <= N; ++a)
            {
                if (N % a != 0) continue;
                long ex = 0; // 指数

                // 割れる限り割り続ける
                while (N % a == 0)
                {
                    ++ex;
                    N /= a;
                }

                // その結果を push
                res.Add((a, ex));
            }

            // 最後に残った数について
            if (N != 1) res.Add((N, 1));
            return res;
        }
    }
    public class ABC_E
    {
        public ABC_E()
        {
        }
    }
    public class ABC_F
    {
        public ABC_F()
        {
        }
    }
    public static class Ex
    {
        public static void Cw(this object s) { Console.WriteLine(s); }



        public static bool Mins<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) > 0) { a = b; return true; } return false; }
        public static bool Maxs<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) < 0) { a = b; return true; } return false; }
        public static void Swap<T>(ref T a, ref T b) { var t = b; b = a; a = t; }
        public static void Swap<T>(List<T> list, int i, int j) { T tmp = list[j]; list[j] = list[i]; list[i] = tmp; }


        static long Gcd(long m, long n) { if (n == 0) return m; return Gcd(n, m % n); }
        public static List<string> FastSort(this List<string> s) { s.Sort(StringComparer.Ordinal); return s.ToList(); }
        public static void yesno(this bool b) { (b ? "yes" : "no").Cw(); }
        public static void YesNo(this bool b) { (b ? "Yes" : "No").Cw(); }
        public static void YESNO(this bool b) { (b ? "YES" : "NO").Cw(); }

        public static string Read { get { return Console.ReadLine().Trim(); } }
        public static int ReadInt { get { return int.Parse(Read); } }
        public static long ReadLong { get { return long.Parse(Read); } }
        public static double ReadDouble { get { return double.Parse(Read); } }
        public static string[] ReadArray() { return Read.Split(' '); }
        public static int[] ReadIntArray() { return Read.Split(' ').Select(int.Parse).ToArray(); }
        public static long[] ReadLongArray() { return Read.Split(' ').Select(long.Parse).ToArray(); }
        public static string[] ReadArray(long N) { var ret = new string[N]; for (long i = 0; i < N; ++i) ret[i] = Read; return ret; }
        public static int[] ReadIntArray(long N) { var ret = new int[N]; for (long i = 0; i < N; ++i) ret[i] = ReadInt; return ret; }
        public static long[] ReadLongArray(long N) { var ret = new long[N]; for (long i = 0; i < N; ++i) ret[i] = ReadLong; return ret; }

        public static int LowerBound<T>(T[] a, T v)
        {
            return LowerBound(a, v, Comparer<T>.Default);
        }

        public static int LowerBound<T>(T[] a, T v, Comparer<T> cmp)
        {
            var l = 0;
            var r = a.Length - 1;
            while (l <= r)
            {
                var mid = l + (r - l) / 2;
                var res = cmp.Compare(a[mid], v);
                if (res == -1) l = mid + 1;
                else r = mid - 1;
            }
            return l;
        }

        /// <summary>
        /// lower_boundは、探索したいkey以上のイテレータを返す
        /// upper_boundは、探索したいkeyより大きいイテレータを返す
        public static int UpperBound<T>(List<T> a, T v)
        {
            return UpperBound(a, v, Comparer<T>.Default);
        }

        public static int UpperBound<T>(List<T> a, T v, Comparer<T> cmp)
        {
            var l = 0;
            var r = a.Count - 1;
            while (l <= r)
            {
                var mid = l + (r - l) / 2;
                var res = cmp.Compare(a[mid], v);
                if (res <= 0) l = mid + 1;
                else r = mid - 1;
            }
            return l;
        }
        public static T1 ReadValue<T1>()
        {
            return (T1)Convert.ChangeType(Read, typeof(T1));
        }

        public static (T1, T2) ReadValue<T1, T2>()
        {
            var inputs = ReadArray();
            var v1 = (T1)Convert.ChangeType(inputs[0], typeof(T1));
            var v2 = (T2)Convert.ChangeType(inputs[1], typeof(T2));
            return (v1, v2);
        }
        public static (T1, T2, T3) ReadValue<T1, T2, T3>()
        {
            var inputs = ReadArray();
            var v1 = (T1)Convert.ChangeType(inputs[0], typeof(T1));
            var v2 = (T2)Convert.ChangeType(inputs[1], typeof(T2));
            var v3 = (T3)Convert.ChangeType(inputs[2], typeof(T3));
            return (v1, v2, v3);
        }
        public static (T1, T2, T3, T4) ReadValue<T1, T2, T3, T4>()
        {
            var inputs = ReadArray();
            var v1 = (T1)Convert.ChangeType(inputs[0], typeof(T1));
            var v2 = (T2)Convert.ChangeType(inputs[1], typeof(T2));
            var v3 = (T3)Convert.ChangeType(inputs[2], typeof(T3));
            var v4 = (T4)Convert.ChangeType(inputs[3], typeof(T4));
            return (v1, v2, v3, v4);
        }
        public static (T1, T2, T3, T4, T5) ReadValue<T1, T2, T3, T4, T5>()
        {
            var inputs = ReadArray();
            var v1 = (T1)Convert.ChangeType(inputs[0], typeof(T1));
            var v2 = (T2)Convert.ChangeType(inputs[1], typeof(T2));
            var v3 = (T3)Convert.ChangeType(inputs[2], typeof(T3));
            var v4 = (T4)Convert.ChangeType(inputs[3], typeof(T4));
            var v5 = (T5)Convert.ChangeType(inputs[4], typeof(T5));
            return (v1, v2, v3, v4, v5);
        }
        public static (T1, T2, T3, T4, T5, T6) ReadValue<T1, T2, T3, T4, T5, T6>()
        {
            var inputs = ReadArray();
            var v1 = (T1)Convert.ChangeType(inputs[0], typeof(T1));
            var v2 = (T2)Convert.ChangeType(inputs[1], typeof(T2));
            var v3 = (T3)Convert.ChangeType(inputs[2], typeof(T3));
            var v4 = (T4)Convert.ChangeType(inputs[3], typeof(T4));
            var v5 = (T5)Convert.ChangeType(inputs[4], typeof(T5));
            var v6 = (T6)Convert.ChangeType(inputs[5], typeof(T6));
            return (v1, v2, v3, v4, v5, v6);
        }
    }
}