Go: package main

import (
	"fmt"
	"math"
)

func main() {
	var on int
	fmt.Scan(&on)
	m := make(map[int]int)
	loop := true
	n := on
	for loop {
		loop = false
		for i := 2; i <= int(math.Sqrt(float64(n))); i++ {
			if n%i == 0 {
				m[i]++
				n /= i
				loop = true
				break
			}
		}
	}
	if n != 1 {
		m[n]++
	}

	var cnt int
	for i := 1; i <= int(math.Sqrt(float64(on))); i++ {
		if on%i == 0 {
			if on/i == i {
				cnt++
			} else {
				cnt += 2
			}
		}
	}

	fmt.Printf("%d %d\n", len(m), cnt-1)
}

C++: #include <stdio.h>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <list>
#include <iterator>
#pragma warning(disable:4996)
 
typedef long long ll;
#define MIN(a, b) ((a)>(b)? (b): (a))
#define MAX(a, b) ((a)<(b)? (b): (a))
#define LINF 9223300000000000000
#define INF 2140000000
#define MOD 1000000007
using namespace std;

vector<long> pp;

void preparePrime( long maxp )
{
    long i;
    vector<long> a(maxp+1);
    for(i=2; i<=maxp; i++) {
        long k=i+i;
        while(k<=maxp) {
            a[k]=1;
            k+=i;
        }
    }
    for(i=2; i<=maxp; i++) {
        if(a[i]==0) pp.push_back( i );
    }
    return;
}

void decompositPrime( ll a, vector<pair<ll,ll> >& vv )
{
    preparePrime( (long)sqrt((double)a) );

    long i;
    for(i=0; i<(long)pp.size(); i++) {
        long count = 0;
        while(a % pp[i] == 0 ) {
            a /= pp[i];
            count ++;
        }
        if(count>0) vv.push_back( make_pair( pp[i], count ) );
        if (a==1) break;
    }
    if(a>1) {
        vv.push_back( make_pair( a, 1 ) );
    }

    return;
}

int main(int argc, char* argv[])
{
    ll n;
    scanf("%lld", &n);

    vector<pair<ll,ll> > vv;
    decompositPrime( n, vv );

    ll num = vv.size();
    ll ans = 1;
    long i;
    for(i=0; i<num; i++) {
        ans *= (vv[i].second+1);
    }

    printf("%lld %lld\n", num, ans-1 );

    return 0;
}

C++: #include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define all(v) v.begin(), v.end()
#define SP << " " 
#define LLi long long int

using namespace std;

vector<LLi> pri={1, 2, 3};

void PV(vector<int> pvv) {
	rep(i, pvv.size()) cout << pvv[i] SP;
	cout << endl;
}

void PVL(vector<LLi> pvv) {
	rep(i, pvv.size()) cout << pvv[i] SP;
	cout << endl;
}

bool VV(vector<int> vv1, vector<int> vv2) {
	if(vv1.size()!=vv2.size()) return false;
	rep(i, vv1.size()) if(vv1[i]!=vv2[i]) return false;

	return true;
}

bool VVL(vector<LLi> vv1, vector<LLi> vv2) {
	if(vv1.size()!=vv2.size()) return false;
	rep(i, vv1.size()) if(vv1[i]!=vv2[i]) return false;

	return true;
}

//vecotr<LLi>の総和
LLi SML(vector<LLi> smv) {
	LLi tmp=0;
	rep(i, smv.size()) tmp+=smv[i];

	return tmp;
}

//n以下の素数を配列に{1, 2, 3, 5, 7, ...} make_prime_list
//i, j, flag, sqx, xを使用
void mplist(LLi x){
	int flag;

	for(int i=5;i<=x;i+=2){
		flag=0;
		for(int j=1;j<(int)pri.size();j++){
			if(i%pri[j]==0){
				flag=1;
				break;
			}
			if(x<pri[j]*pri[j]) break;
		}
		if(flag==0) pri.emplace_back(i);
	}
}

//nを素因数分解 root_prime_fac
//i, tmp, bin, lmt, xを使用
map<LLi, int> rpfac(LLi x){
	int sqx=ceil(sqrt(x));
	//cout<< "sqx=" << sqx SP << sqx*sqx << endl;//
	auto bin = lower_bound(all(pri), sqx);
	int lmt=bin-pri.begin()+1;
	map<LLi, int> tmp;
	//cout<< "lmt=" << lmt SP << pri[lmt] SP << pri[lmt]*pri[lmt] <<endl;//
	if((int)pri.size()<lmt) cout<< "rpfac: pri size is small" <<endl;

	for(int i=1;i<lmt;i++){
		while(x%pri[i]==0){
			x/=pri[i];
			tmp[pri[i]]++;
			//cout<< x <<endl;
			//tmp[0]++;//0番に何個の積でできてるかをメモれる
		}
		if(x==1) break;
	}

	//if(x!=1) cout<< "prime_fac x=" << x <<endl;
	return tmp;
}

//階乗を素因数分解
map<LLi, int> facfac(LLi x){
	map<LLi, int> tmp;
	auto bin = lower_bound(all(pri), x);
	int lmt=bin-pri.begin()+1;
  	//cout<< "lmt=" << lmt SP << pri[lmt] SP << pri[lmt]*pri[lmt] <<endl;//

	for(LLi i=1;i<lmt;i++){
		int lp=0, di=0;
		while(pow(pri[i], lp)<x){
			lp++;
			di+=x/pow(pri[i], lp);
		}
		if(di>0) tmp[pri[i]]=di;
	}
	
	return tmp;
}

//約数列挙
//i, j, k, tmp, mul, mを使用
vector<LLi> getfac(map<LLi, int> mp){
	vector<LLi> tmp={1}, ad;
	LLi mul;
	
	for (auto p : mp) {
		mul=1;
		ad.clear();
  		LLi key = p.first;
  		int value = p.second;
		  
		rep(j, value){
			mul*=key;
			rep(k, tmp.size()) ad.push_back(tmp[k]*mul);
		}
		rep(j, ad.size()) tmp.push_back(ad[j]);
		//PV(tmp);//
	}

	/*for(int i=1;i<v.size();i++){
		if(v[i]==0) continue;
		mul=1;
		ad.clear();
		rep(j, v[i]){
			mul*=pri[i];
			rep(k, tmp.size()){
				ad.push_back(tmp[k]*mul);
			}
		}
		//PV(tmp);
		rep(j, ad.size()) tmp.push_back(ad[j]);
	}*/

	sort(all(tmp));
	return tmp;
}

//素因数の積を計算
//i, tmp, vを使用
LLi defac(map<LLi, int> mp){
	LLi tmp=1;

	/*for(int i=1;i<v.size();i++){
		if(v[i]!=0) tmp*=pow(pri[i], v[i]);
	}*/

	for (auto p : mp) {
  		LLi key = p.first;
  		int value = p.second;
		tmp*=pow(key, value);
	}

	return tmp;
}

//素数判定 is_prime
//ub, lb, x, iを使用
bool isp(LLi x){
	//if(x==1) return false;//1を素数としないなら有効化
	auto ub = upper_bound(all(pri), x);
	auto lb = lower_bound(all(pri), x);

	//xがでかいときは素数リストで割ってみる
	if(lb==pri.end()){
		for(int i=1;i<(int)pri.size();i++){
			if(x%pri[i]==0) return false;
			if(x<pri[i]*pri[i]) return true;
		}
		//cout<< "isp: pri size is small" <<endl;

		//priのサイズが足りないときは地道にチェックする
		for(LLi i=pri[pri.size()-1]+2;i*i<=x;i+=2){
			if(x%i==0) return false;
		}
		return true;
	}

	return ub!=lb;
}

int main(){

	LLi n, m, ml;
	vector<LLi> v;
	map<LLi, int> mp;

	cin>> m;

	mplist(1000100);//nまでの素数列挙
	//PVL(pri);//
	mp=rpfac(m);//mを√mまで素因数分解
	ml=defac(mp);//mlにmpの総積を代入
	//cout<< "m/ml=" << m/ml SP << isp(m/ml) <<endl;//
	if(m!=ml) mp[m/ml]++;//mpにm/mlを追加(√m以上の素数が約数の場合に必要な処理)
	//mの約数で√m以上の素数は1つしかないのでこれでOK

	for (auto p : mp) {
  		auto key = p.first;
  		auto value = p.second;
		//cout<< key << "^" << value SP;//mpの内訳を表示
	}
	
	v=getfac(mp);//素因数分解から約数を列挙

        cout<< mp.size() << " " << v.size()-1 <<endl;

	return 0;
}

C++: #include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<string>
#include<algorithm>
#include<vector> 
#include<limits>
#include<numeric>
#include<type_traits>
#include<math.h>
#include<fstream>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;

#define rep(i, n) for(int i = 0; i < (int)(n); i++)
#define repi(i,a,b) for(int i = (int)(a); i < (int)(b); i++)
#define out(str) cout << str << endl
#define ALL(a) (a).begin(),(a).end()
#define INF (1<<29)

template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }

const int N = 1001000;
bool prime[1001000];
void eratosthenes(){
    rep(i,N) prime[i] = 1;
    prime[0] = prime[1] = 0;
    rep(i,N){
        if(prime[i]){
            for(int j = i + i; j < N; j+=i){
                prime[j] = 0;
            }
        }
    }
}

ll n,now=1,p=0;

int main(){
    eratosthenes();
    cin>>n;
    rep(i,sqrt(n)+2){
        if(prime[i]){
            if(n%i!=0)continue;
            ll cnt=0;
            while(n%i==0){
                cnt++;
                n/=i;
            }
            now*=(cnt+1);
            p++;
        }
    }
    if(n!=1){
        now*=2;
        p++;
    }
    if(now==1)cout<<"1 1"<<endl;
    else cout<<p<<" "<<now-1<<endl;
    
    
}