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

using ll = long long;
using ld  = long double;
using pll = pair<ll, ll>;
using pld = pair<ld, ld>;
const int INF=1e9+7;
const ll LINF=9223372036854775807;
const ll MOD=1e9+7;
const ld PI=acos(-1);
const ld EPS = 1e-10; //微調整用（EPSより小さいと0と判定など）

int ii() { int x; if (scanf("%d", &x)==1) return x; else return 0; }
long long il() { long long x; if (scanf("%lld", &x)==1) return x; else return 0; }
string is() { string x; cin >> x; return x; }
char ic() { char x; cin >> x; return x; }
void oi(int x) { printf("%d ", x); }
void ol(long long x) { printf("%lld ", x); }
void od_nosp(double x) { printf("%.15f", x); } // 古い問題用
void od(double x) { printf("%.15f ", x); }
void os(const string &s) { printf("%s ", s.c_str()); }
void oc(const char &c) { printf("%c ", c); }
#define o_map(v){cerr << #v << endl; for(const auto& xxx: v){cout << xxx.first << " " << xxx.second << "\n";}} //動作未確認
void br() { putchar('\n'); }

// #define gcd __gcd //llは受け取らない C++17~のgcdと違うので注意
// int lcm(int a, int b){return a / gcd(a, b) * b;}
#define b_e(a) a.begin(),a.end() //sort(b_e(vec));
#define REP(i,m,n) for(ll i=(ll)(m) ; i < (ll)(n) ; i++ )
#define DREP(i,m,n) for(ll i=(ll)(m) ; i > (ll)(n) ; i-- )
#define rep(i,n) REP(i,0,n)
#define m_p(a,b) make_pair(a,b)
#define p_b push_back
#define SZ(x) ((ll)(x).size()) //size()がunsignedなのでエラー避けに
#define endk '\n'


// coutによるpairの出力（空白区切り）
template<typename T1, typename T2> ostream& operator<<(ostream& s, const pair<T1, T2>& p) {return s << "(" << p.first << " " << p.second << ")";}
// coutによるvectorの出力（空白区切り）
template<typename T> ostream& operator<<(ostream& s, const vector<T>& v) {
  int len = v.size();
  for (int i = 0; i < len; ++i) {
    s << v[i]; if (i < len - 1) s << " "; //"\t"に変えるとTabで見やすく区切る
  }
  return s;
}
// coutによる多次元vectorの出力（空白区切り）
template<typename T> ostream& operator<<(ostream& s, const vector< vector<T> >& vv) {
  int len = vv.size();
  for (int i = 0; i < len; ++i) {
    s << vv[i] << endl;
  }
  return s;
}

//最大値、最小値の更新。更新したor等しければtrueを返す
template<typename T>
bool chmax(T& a, T b){return (a = max(a, b)) == b;}
template<typename T>
bool chmin(T& a, T b){return (a = min(a, b)) == b;}

//4近傍（上下左右） rep(i, 2) にすると右・下だけに進む
vector<int> dx_4 = {1, 0, -1, 0};
vector<int> dy_4 = {0, 1, 0, -1};

// -------- template end - //


// - library ------------- //

// #include <atcoder/all>
// using namespace atcoder;

// 10^18まではいけるようだが、10^19でオーバーフローする
// MODをつけたい場合もこれでもいい
// 繰り返し二乗法を使っているので O(logN) で計算できる
ll llpow(ll x, ll n){
  ll ans = 1;
  while (n > 0){
    if (n % 2 == 1) ans = ans * x; // % MOD; (MODつけたい場合のコピー用)
    x = x * x; // % MOD; (MODつけたい場合のコピー用)
    n /= 2; // n を右に1つビットシフト
  }
  return ans;
}

// エラトステネスの篩に基づく高速な素因数分解
// 前処理したあと O(logN)でNを素因数分解
// 以下のページのライブラリを改造したもの
// https://qiita.com/rsk0315_h4x/items/ff3b542a4468679fb409
class smart_sieve {
  ll L, R, M;
  std::vector<int> small;  // 小さい篩
  std::vector<std::vector<ll>> large;  // 大きい篩
  std::vector<ll> aux;  // aux[i] := large[i] の素因数の積

public:
  smart_sieve(ll L, ll R): L(L), R(R), M(sqrt(R)+1) {
    small.resize(M);
    std::iota(small.begin(), small.end(), 0);
    large.resize(R-L);
    aux.assign(R-L, 1);

    for (ll i = 2; i*i < R; ++i) {
      if (small[i] < i) continue;
      small[i] = i;
      for (ll j = i*i; j < M; j += i)
        if (small[j] == j) small[j] = i;

      for (ll j = (L+i-1)/i*i; j < R; j += i) {
        ll k = j;
        do {
          // aux[j-L] > M で判定した方がいいかも？
          // j / aux[j-L] < M の方がいい？（割り算したくない）
          if (aux[j-L] * aux[j-L] > R) break;

          large[j-L].push_back(i);
          aux[j-L] *= i;
          k /= i;
        } while (k % i == 0);
      }
    }
  }

  // 素因数分解 O(logN) 
  // factor(i) : i の素因数vector : f(120) = 2 2 2 3 5（ソート済）
  // 0 を渡すと おかしい答えが返ってくる。
  // 1 を渡すと {} を返す。
  std::vector<ll> prime_factorize(ll n) {
    assert(L <= n && n < R);
    std::vector<ll> res = large[n-L];
    n /= aux[n-L];
    if (n >= M) {
      // この場合，n は素数となることが示せる（はず）
      // n*n >= R だとオーバーフローしそう？
      res.push_back(n);
      return res;
    }
    while (n > 1) {
      res.push_back(small[n]);
      n /= small[n];
    }
    return res;
  }

  // 約数列挙ライブラリ（ llpow() を含めること！）
  // 非ソート約数列挙 O(logN)+O(dN) ※第二引数を渡さない場合
  // ソート約数列挙 O(logN)+O(dN)+O(dNlogdN) ※第二引数を true に
  // ※ dN = d(N) = σ0(N) = 自然数Nの約数の個数

  // ソート約数列挙をする際は約数の個数に注意
  // その範囲の高度合成数を見れば、約数の個数のmaxが大体分かる
  // （高度合成数一覧）http://wwwhomes.uni-bielefeld.de/achim/highly.txt
  // N<=10^9のとき、log(N)=約30, 約数の個数の最大は735,134,400の1,344個
  // --> ソート約数列挙 : 30+1344+1344*30= 41,694回
  // N<=10^8 のとき O(27)+O(768)+O(768*27)= 21,531回
  // N<=10^7のときd(N)最大は448, N<=10^6のときd(N)最大は240
  // 結論：ソート約数列挙はlong longの範囲内なら全部いけそうだが、1~Nについて行うのは10^5でギリギリか
  std::vector<ll> divisors(ll n, bool sorted = false) {
    assert(L <= n && n < R);
    std::vector<ll> pfactors = large[n-L];
    n /= aux[n-L];
    bool n_is_prime = false;
    if (n >= M) {
      // この場合，n は素数となることが示せる（はず）
      // n*n >= R だとオーバーフローしそう？
      pfactors.push_back(n);
      n_is_prime = true;
    }
    if (!n_is_prime){
      while (n > 1) {
        pfactors.push_back(small[n]);
        n /= small[n];
      }
    }

    map<ll, ll> map_pfactors;
    for (ll pfac : pfactors){
      map_pfactors[pfac]++;
    }

    // 約数列挙
    std::vector<ll> res;
    ll len = ll(map_pfactors.size()); // 素因数の種類数
    // 再帰関数で約数を列挙
    make_divisors_from_pfacs(map_pfactors, res, 1, 0);

    // 第二引数が true だった場合、 res をソート
    if (sorted) sort(res.begin(), res.end());

    return res;
  }

  // <素因数, 個数> のmapを受け取り、vector resに約数を入れる再帰関数
  // depth := 今見るべき素因数が何個目か(0-indexed) -> map_pfactors[depth]
  void make_divisors_from_pfacs(map<ll, ll> &map_pfactors, vector<ll> &divs_vec, ll nowres, ll depth){
    auto itr = next(map_pfactors.begin(), depth);
    if (itr == map_pfactors.end()){
      // 全ての素因数を処理し終わったので、約数をvectorに入れて終了
      // 素因数が1つも無い場合（n=1の場合）、最初からこれになるので、1のみが約数として返される
      divs_vec.push_back(nowres);
      return;
    }
    ll nowpfac = (*itr).first;
    ll nowpfacnum = (*itr).second;
    ll multiplier = 1;
    rep(i, nowpfacnum+1){
      ll tmpres = nowres * multiplier;
      make_divisors_from_pfacs(map_pfactors, divs_vec, tmpres, depth+1);
      multiplier *= nowpfac;
    }
  }


};

// --------- library end - //



int main(){

  ll N = il();

    // smart_sieve(L, R) で [L, R) を前計算
  ll L = 1;
  ll R = 1000001;
  smart_sieve ss(L, R);



  ll ans = 0;
  REP(c, 1, 1000000){
    if (c >= N) break;

    // Aの約数の数だけ、Bがある
    ans += SZ(ss.divisors(N-c));
  }

  cout << ans << endk;


  

}



Measured memory_bytes: 78304