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: Time Limit Exceeded)


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;

namespace at_coder
{
#if TEST
    [TestClass]
#endif
    public class Test_169_d
    {

#if TEST
        public static void Test_Main()
#else
        public static void Main()
#endif
        {
            long N = ReadLong();
            long M = N;
            List<int> pList = new List<int>();
            Dictionary<int, int> divCount = new Dictionary<int, int>();
            // 素数を求める
            int a = 2;
            int ans = 0;
            int[] primeList = new int[100000];
            int primeN = 0;
            long Q = (long) Math.Sqrt(N);

            while(a <= Math.Min(Q, N))
            {
                bool primeCheck = false;

                for(int i=0;i<primeN;i++)
                {
                    int prime = primeList[i];
                    if (a % prime == 0)
                    {
                        // 素数で割れるので対象外
                        primeCheck = true;
                        break;
                    }
                }

                if (primeCheck == false)
                {
                    if (N % a == 0)
                    {
                        // 素数が見つかった場合
                        N = N / a;
                        divCount[a] = 1;
                        while(N % a == 0)
                        {
                            N = N / a;
                            divCount[a]++;
                        }

                        // 素数の ^ ss 乗
                        int ss = divCount[a];

                        // ss を 1,2,3,4 と 減算する
                        for(int i=1;i<10000;i++)
                        {
                            if (ss >= i)
                            {
                                ss -= i;
                                ans++;
                            }
                        }
#if DEBUG
                        Debug.Print($"{divCount[a]}");
#endif

                    }
                    primeList[primeN] = a;
                    primeN++;
#if DEBUG
                    Debug.Print($"{a}");
#endif
                }
                a++;
            }
            if (divCount.Count == 0 && M > 1)
            {
                // それ自身が素数の場合
                ans++;
            }
            Write($"{ans}");
        }


        private static void Write(string s)
        {
            Console.WriteLine(s);
        }

        private static int[] ReadIntArray()
        {
            string[] ss = Console.ReadLine().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            int[] ar = new int[ss.Length];
            for (int i = 0; i < ss.Length; i++)
            {
                ar[i] = int.Parse(ss[i], CultureInfo.InvariantCulture);
            }
            return ar;
        }
        private static long ReadLong()
        {
            return long.Parse(Console.ReadLine(), CultureInfo.InvariantCulture);
        }
        private static void ReadInt(out int a, out int b)
        {
            var ar = ReadIntArray();
            a = ar[0];
            b = ar[1];
        }
        private static void ReadInt(out int a, out int b, out int c)
        {
            var ar = ReadIntArray();
            a = ar[0];
            b = ar[1];
            c = ar[2];
        }
        private static string ReadString()
        {
            return Console.ReadLine();
        }
        private static string[] ReadStringArray()
        {
            string[] ss = Console.ReadLine().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            return ss;
        }
#if !TEST
    }
}
#endif