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.Collections.Generic;
using System.Numerics;
using System.Linq;
using System.Text;
using static System.Math;

class MainClass
{


    public static void Main(string[] args)
    {
        var N = LnLng();
        var fact = new Factorization(N);
   var res= fact.Calc();
        var dict = new Dictionary<long, int>();
        foreach(var i in res)
        {
            try{
                dict[i]++;
            }
            catch
            {
                dict.Add(i, 1);
            }
        }
        long count = 0;
        foreach(var i in dict)
        {
            var n = i.Value;
            var minus = 1;
            while (n - minus >= 0)
            {
                n -= minus;
                count++;
                minus++;
            }
        }
        print(count);
    }

    public class Factorization
    {
        private static long N;

        public Factorization(long n) { N = n; }

        //最大公約数を返す
        public static long GCD(long a, long b)
        {
            if (a < b) return GCD(b, a);
            long r;
            while (b != 0)
            {
                r = a % b;
                a = b;
                b = r;
            }
            return a;
        }

        //素数判定
        public static bool IsPrime(long n)
        {
            if (n < 2) return false;
            if (n == 2) return true;
            if (n % 2 == 0) return false;

            double root = Math.Sqrt(n);
            for (int i = 3; i <= root; i += 2)
            {
                if (n % i == 0) return false;
            }
            return true;
        }

        //試し割り
        private static int[] TryPrimes = new int[] { 2, 3, 5, 7, 11 };
        public long TryAllocation(long p)
        {
            long count = 0;
            while (N % p == 0)
            {
                count++;
                N /= p;
            }
            return count;
        }

        private int[] xi = new int[] { 13, 17, 19, 23, 29 };
        private long f(long x, int suffix)
        {
            return (xi[suffix % xi.Count()] * x + suffix) % N;
        }

        //nを分解
        public long PollardsRho(long n, int suffix = 0)
        {
            //素数を渡すと失敗するらしい
            if (IsPrime(n)) return n; //もう素数
            long x = 2, y = 2, d = 1;
            while (d == 1)
            {
                x = f(x, suffix);
                y = f(f(y, suffix), suffix);
                d = GCD(Math.Abs(x - y), n);
            }
            if (d == n)
            {
                //f(x)を変えて試す
                return PollardsRho(n, suffix + 1);
            }
            return d;
        }

        public IEnumerable<long> Calc()
        {
            //小さな素因数の計算
            foreach (var prime in TryPrimes)
            {
                var box = TryAllocation(prime);
                for (int i = 0; i < box; i++) yield return prime;
            }

            //残りをRhoで解く
            while (true)
            {
                if (N == 1) break;
                var ret = PollardsRho(N);
                yield return ret;
                N /= ret;
            }
        }
    }

    public static long SumAtoB(long a, long b) { var length = b - a + 1; return (a + b) * (length / 2) + (length % 2 == 1 ? (a + b) / 2 : 0); }
    public static long PowLite(long n, long p, long mod = (long)1e9 + 7) { long ans = 1; long now = n; for (; p > 0; p >>= 1) { if ((p & 1) == 1) { ans *= now; ans %= mod; } now *= now; now %= mod; } return ans; }
    public static void print(object obj) { Console.WriteLine(obj); }
    public static long Gcd(long a, long b) { if (a > b) { var r = a % b; if (r == 0) return b; else return Gcd(b, r); } else { var r = b % a; if (r == 0) return a; else return Gcd(a, r); } }
    public static int Gcd(int a, int b) { if (a > b) { var r = a % b; if (r == 0) return b; else return Gcd(b, r); } else { var r = b % a; if (r == 0) return a; else return Gcd(a, r); } }
    public static int[] LnInts() { var vs = Console.ReadLine().Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var ins = new int[vs.Length]; for (int i = 0; i < vs.Length; i++) ins[i] = int.Parse(vs[i]); return ins; }
    public static int LnInt() { var vs = Console.ReadLine().Trim(); return int.Parse(vs); }
    public static long[] LnLngs() { var vs = Console.ReadLine().Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var ins = new long[vs.Length]; for (int i = 0; i < vs.Length; i++) ins[i] = long.Parse(vs[i]); return ins; }
    public static long LnLng() { var vs = Console.ReadLine().Trim(); return long.Parse(vs); }
    public static string[] LnStrs() { var vs = Console.ReadLine().Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); return vs; }
    public static string LnStr() { var vs = Console.ReadLine().Trim(); return vs; }
    public static List<T[]> AllPermutation<T>(params T[] array) where T : IComparable { var a = new List<T>(array).ToArray(); var res = new List<T[]>(); res.Add(new List<T>(a).ToArray()); var n = a.Length; var next = true; while (next) { next = false; int i; for (i = n - 2; i >= 0; i--) { if (a[i].CompareTo(a[i + 1]) < 0) break; } if (i < 0) break; var j = n; do { j--; } while (a[i].CompareTo(a[j]) > 0); if (a[i].CompareTo(a[j]) < 0) { var tmp = a[i]; a[i] = a[j]; a[j] = tmp; Array.Reverse(a, i + 1, n - i - 1); res.Add(new List<T>(a).ToArray()); next = true; } } return res; }
}