// Standard Stuff
#include <bits/stdc++.h>
using namespace std;

// Macros
#define F  first
#define S  second
#define PB push_back
#define MP make_pair
#define ALL(container)   container.begin(),container.end()
#define RALL(container)  container.rbegin(),container.rend()
#define MAKE_UNIQUE(vec) vec.erase(unique(ALL(vec)),vec.end())

// Rename Datatypes
using ll  = long long;
using ld  = long double;
using pii = std::pair <int,int>;

// Random
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
/* [a,b] */ template<class T> T rnd_IntType(T a, T b){ return uniform_int_distribution<T>(a, b)(rng); }
/* [a,b) */ template<class T> T rnd_RealType(T a, T b){ return uniform_real_distribution<T>(a,b)(rng); }

// Common Functions
ll fastpow(ll a, ll ex){ ll res = 1; while(ex){ if(ex & 1) res *= a; a *= a; ex >>= 1; } return res; }
ll fastpow(ll a, ll ex, ll m){ a %= m; ll res = 1; while(ex){ if(ex & 1) res = (a*res) % m; a = (a*a) % m; ex >>= 1; } return res; }
ll modinverse(ll a, ll m){ ll m0 = m, y = 0, x = 1; while (a > 1){ ll q = a / m; a %= m; swap(a,m); x -= q*y; swap(x,y); } if(x < 0) x += m0; return x; }

// Output, Common Containers
template <typename T> ostream& operator << (ostream &os, const vector<T> &v) { for (T i : v) os << i << ' '; return os; }
template <typename T> ostream& operator << (ostream &os, const set<T> &v)    { for (T i : v) os << i << ' '; return os; }
template <typename T> ostream& operator << (ostream &os, const deque<T> &v)  { for (T i : v) os << i << ' '; return os; }
template <typename T, typename S> ostream& operator << (ostream &os, const pair<T,S> &v) { os << "(" << v.F << "=>" << v.S << ") "; return os; }
template <typename T, typename S> ostream& operator << (ostream &os, const map<T,S> &v)  { for (auto i : v) os << i << ' '; return os; }

// Debugging
#ifdef LOCAL
	#define trace(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); d__f(_it, args); }
	void d__f(__attribute__((unused)) istream_iterator<string> it) {}
	template<typename Head, typename... Tail> void d__f(istream_iterator<string> it, Head H, Tail... T) { cerr << *it << " <=> [" << H << "]\n"; d__f(++it, T...); }
#else
	#define trace(args...)
#endif

//Faster Sieve
// smallest_prime => min prime factor
// primes ==> contains all primes
vector<int> smallest_prime, primes;
void init_sieve(int max_sz){
	smallest_prime.resize(max_sz+1,0);

	smallest_prime[0] = smallest_prime[1] = -1;

	for(int i = 4; i <= max_sz; i += 2) smallest_prime[i] = 2;

	for(int i = 3; i*i <= max_sz; i += 2)
		if(! smallest_prime[i])
			for(int j = i*i; j <= max_sz; j += 2*i)
				if(! smallest_prime[j])
					smallest_prime[j] = i;

	for(int i = 2; i <= max_sz; ++i)
		if(! smallest_prime[i]){
			smallest_prime[i] = i;
			primes.PB(i);
		}
}

void solve(){
	ll n;
	cin >> n;

	ll ans = 0;

	for(auto p: primes){
		int cnt = 0;
		while(n % p == 0){
			++cnt;
			n /= p;
		}

		if(cnt == 0) continue;

		int temp = 0;

		for(int i = 1; i <= cnt; ++i){
			if((i * (i+1) / 2) <= cnt)
				temp = max(temp, i);
		}

		ans += temp;
	}

	if(n > 1) ++ans;

	cout << ans << "\n";
}

signed main (void){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	init_sieve(1e6+10);

	int tt = 1;
	// cin >> tt;
	while(tt--) solve();
}

Measured memory_bytes: 7836