#include <vector>
#include <iostream>
#include <cmath>
#include <iomanip>
#include <string>
#include <utility>
#include <stack>
#include <numeric>
#include <random>
#include <algorithm>
#include <queue>
#include <functional>
#include <iterator>
#include <list>
#include <unordered_map>
#include <deque>
#include <math.h>
#include <tgmath.h>
#include <cstdlib>
#include <set>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define rep(i, b, e) for(i = b; i < e; ++i)
#define repr(i, b, e) for (i = b; i >= e; --i)
#define ull unsigned long long int
#define ll long long int
#define pint pair<int, int>

#define M_DEBUG 1
#define PI 3.141592653589793

#define E '\n'

#define printt(x) cout << (x) << endl;
#define printa(x,n) for(int i = 0; i < n; i++){ cout << (x[i]) << "\n";}
#define INF (1e18)

const ll MAX = 1000000000;
const ll MOD = 1e9 + 7;

ll a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;

template<typename T> 
bool chmin(T& a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template<typename T> 
bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

ll aabs(ll a) {
    if (a < 0) return -a;
    return a;
}

//fast power
ll calc(ll a, ll b) {
    if (b == 0) return 1;
    else if (b % 2 == 0) {
        ll d = calc(a, b / 2);
        return (d * d) % MOD;
    }
    else return (a * calc(a, b - 1)) % MOD;
}

//fast combination
ll comb(ll n, ll a) {
    ll b = 1, c = 1;
    for (ll i = 1; i <= a; ++i) {
        b = b * i % MOD;
        c = c * (n - i + 1) % MOD;
    }

    return c * calc(b, MOD - 2) % MOD;
}

ll comb2(ll a) {
    ll b = a / 2;
    if (a % 2) {
        b = (a - 1) / 2;
        return (b * a);
    }
    return (b * (a - 1));
}

ll gcd_impl( ll n, ll m ) {
        for( int i = 0; i < 10; ++i ) {
                ll t = n - m;
                bool q = m > t;
                n = q ? m : t;
                m = q ? t : m;
                if( m == 0 ) { return n; }
        }
        return gcd_impl( m, n % m );
}

ll gcd( ll n, ll m ) {
        return n > m ? gcd_impl( n, m ) : gcd_impl( m, n );
}

const int INF_ = 1e+7;

//0-indexed

struct Node {
    std::vector<int> nodes;
    std::vector<int> edge_costs;

    int num = 0;
    int cost = INF_;
    int link_out = 0;
    int link_in = 0;
    int pcost = -1;
};

class Graph {
public:
    Graph(int n, bool directed);
    ~Graph();
    
    void initGraph(int n, int cost);
    void setGraph(int n, int node, int edge_cost);
    void Dijkstra(int start);
    void print();
    std::vector<int> topologicalSort();
    std::vector<int> topologicalSort(int st);
    int solve();
    void solve2();

    int longestPath();

    void nodesWithRank(int n, int i, int rank, vector<int>& ranks, vector<bool>& dup);
    vector<int> nodesWithRank(int n, int rank);

    int ans = 0;

public:
    std::vector<Node> m_graph;
    int m_size;
    bool m_directed = false;
};


Graph::Graph(int n, bool directed) : m_size(n), m_directed(directed) {
    m_graph = std::vector<Node>(m_size);
}

Graph::~Graph(){}

void Graph::initGraph(int n, int cost) {
    n--;
    m_graph[n].cost = cost;
}


void Graph::setGraph(int n, int node, int edge_cost) {
    --n;
    --node;
    for (int i : m_graph[n].nodes) {
        if (i == node) return;
    }
    ++m_graph[node].link_in;
    m_graph[n].nodes.emplace_back(node);
    m_graph[n].edge_costs.emplace_back(edge_cost);
    ++m_graph[n].link_out;
}

void Graph::Dijkstra(int start) {
    m_graph[start].cost = 0;
    std::queue<int> q;
    q.push(start);
    while (!q.empty()) {
        int qi = q.front();q.pop();

        for (int i = 0; i < m_graph[qi].nodes.size(); ++i) {
            int qqi = m_graph[qi].nodes[i], new_cost = m_graph[qi].edge_costs[i] + m_graph[qi].cost;
            if (m_graph[qqi].cost > new_cost) {
                m_graph[qqi].cost = new_cost;
                q.push(qqi);
            }
        }
    }
}

int Graph::longestPath() {
    int mx = 0;
    for (auto&& g : m_graph) {
        if (g.pcost > mx) mx = g.pcost;
    }
    return mx;
}

void Graph::print() {
    for (int i = 0; i < m_size; ++i) {  
        std::cout << i + 1 << " : ";
        for (int j = 0; j < m_graph[i].nodes.size(); ++j) 
            std::cout << m_graph[i].nodes[j] + 1 << ", ";
        std::cout << std::endl;
    }

    for (int i = 0; i < m_size; ++i) 
        std::cout << i + 1 << " : " << m_graph[i].cost << std::endl;
}

std::vector<int> Graph::topologicalSort() {
    std::queue<int> q;        
    for (int i = 0; i < m_size; ++i)
        if (m_graph[i].link_in == 0) {
            q.push(i);
            m_graph[i].pcost = 1;
        }

    std::vector<int> topo;
    std::vector<int> tmp(m_size);
    for (int i = 0; i < m_size; ++i) tmp[i] = m_graph[i].link_in;

    while (!q.empty()) {
        
        int i = q.front();q.pop();
        topo.emplace_back(i);

        for (auto&& j : m_graph[i].nodes) {
            m_graph[j].link_in--;
            if (m_graph[j].link_in == 0) {
                q.push(j);
                m_graph[j].pcost = m_graph[i].pcost + 1;
            }
        }
    }

    for (int i = 0; i < m_size; ++i) m_graph[i].link_in = tmp[i];

    return topo;
}

std::vector<int> Graph::topologicalSort(int st) {
    std::queue<int> q;        
    for (int i = st; i < m_size; ++i)
        if (m_graph[i].link_in == 0) {
            q.push(i);
            m_graph[i].pcost = 1;
        }

    std::vector<int> topo;
    std::vector<int> tmp(m_size);
    for (int i = 0; i < m_size; ++i) tmp[i] = m_graph[i].link_in;

    while (!q.empty()) {
        
        int i = q.front();q.pop();
        topo.emplace_back(i);

        for (auto&& j : m_graph[i].nodes) {
            m_graph[j].link_in--;
            if (m_graph[j].link_in == 0) {
                q.push(j);
                m_graph[j].pcost = m_graph[i].pcost + 1;
            }
        }
    }

    for (int i = 0; i < m_size; ++i) m_graph[i].link_in = tmp[i];

    return topo;
}


struct HashPair {

    //注意 constがいる
    template<class T1, class T2>
    size_t operator()(const pair<T1, T2> &p) const {

        auto hash1 = hash<T1>{}(p.first);

        auto hash2 = hash<T2>{}(p.second);

        size_t seed = 0;
        seed ^= hash1 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
        seed ^= hash2 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
        return seed;
    }
};

vector<vector<ll> > vv;
ll ans = 0, aa = 0;
bool flg = false;
void dfs(int i, vector<vector<int>> a, int xo) {
    if (i + 1 == n) {
        if (xo == 0) 
            flg = true;
        return;
    }
    for (int j = 0; j < k; ++j) {
        dfs(i + 1, a, a[i + 1][j] ^ xo);
    }
}

void Graph::nodesWithRank(int n, int i, int rank, vector<int>& ranks, vector<bool>& dup) {
    //cout << i + 1 << endl;
    if (n == i) return;
    if (rank == 0) {
        for (int j = 0; j < m_graph[i].nodes.size(); ++j) {
            if (m_graph[i].nodes[j] == n)
                return;
        }
        if (dup[i]) return;
        dup[i] = true;
        ranks.emplace_back(i);
        return;
    }
    for (int k : m_graph[i].nodes) 
        nodesWithRank(n, k, rank - 1, ranks, dup);
}

vector<int> Graph::nodesWithRank(int n, int rank) {
    vector<int> ranks;
    vector<bool> dup(m_size, false);
    for (int k : m_graph[n].nodes) 
        nodesWithRank(n, k, rank - 1, ranks, dup);
    return ranks;
}

int Graph::solve() { return 0; }

void Graph::solve2() {
    for (int i = 0; i < m_size; ++i) 
        cout << nodesWithRank(i, 2).size() << endl;
}

vector<pair<ll, ll> > prime_factorize(ll N) {
    vector<pair<ll, ll> > res;
    for (ll a = 2; a * a <= N; ++a) {
        if (N % a != 0) continue;
        ll ex = 0; // 指数

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

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

    // 最後に残った数について
    if (N != 1) res.push_back({N, 1});
    return res;
}

int main() {
    ll N;
    unordered_map<ll, bool> um; 
    cin >> N;
    if (N == 1) {
        cout << 0 << endl;
        return 0;
    }
    c = N;
    vector<pair<ll, ll> > res = prime_factorize(N);
    ll pre = res[0].first;
    //cout << res[0].first << " " << res[0].second << endl;
    res[0] = make_pair(res[0].first, res[0].second - 1);
    //cout << res[0].first << " " << res[0].second << endl;

    b = 0;
    /*for (auto p : res) {
            rep (i, 0, p.second) {
                cout << p.first << " ";
            }
    }
    cout << endl;
*/
    while (N > 1 && res.size()) {
        ++b;
        if (pre == 0) {
            break;
        }
        N /= pre;
        um[pre] = true;
        bool flg = true;
        ll min = c;
        e = 0;
        d = 0;
        pair<ll, ll> pa;
        for (size_t j = 0; j < res.size(); ++j) {
            //cout << res[j].first << "  " << res[j].second << endl;
            rep (i, 0, res[j].second) {
                a = pow(res[j].first, (i + 1));
                if (a < min && um[a] != true) {
                    min = a;
                    e = j;
                    d = (i + 1);
                    flg = false;
                }
            }
        }
        if (flg) break;
        pre = min;
        res[e] = make_pair(res[e].first, res[e].second - d);
        //cout << pre << endl;
    }
    cout << b << endl;
}


Measured memory_bytes: 4076