#pragma region template
// clang-format off
#if defined ONLINE_JUDGE
  #pragma GCC target("avx2")
  #pragma GCC optimize("tree-vectorize")
  #define here
  #define com(msg)
  #define watch(...)
  #define watchVec(vec)
  #define local(x)
  #define alter(x,y) y
  #define M_assert(expr) do{if(!expr) vector<int> MLE_(3e8, 0);} while(0)
  #define O_assert(expr) do{if(!expr) while(1) printf("Hello, world!\n");} while(0)
#elif defined LOCAL_JUDGE
  #pragma GCC target("avx2")
  #pragma GCC optimize("tree-vectorize")
  #define here
  #define com(msg)
  #define watch(...)
  #define watchVec(vec)
  #define local(x)
  #define alter(x,y) y
  #define M_assert(expr) assert(expr)
  #define O_assert(expr) assert(expr)
#else
  #define here cerr<<__func__<<"/"<<__LINE__<<": reached\n"
  #define com(msg) cerr<<"{ "<<msg<< " }\n"
  #define watch(...) observe(#__VA_ARGS__,__VA_ARGS__)
  #define watchVec(vec) do{cerr<<#vec<<": ";printv(#vec,vec);} while(0)
  #define local(x) do{x} while(0)
  #define alter(x,y) x
  #define M_assert(expr) assert(expr)
  #define O_assert(expr) assert(expr)
#endif

#include <bits/stdc++.h>
#include <boost/range/irange.hpp>
#include <boost/multiprecision/cpp_int.hpp>

#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define rep(i,n) for(int i=0;i<(n);i++)
#define rng(i,f,t,s) for(int i : boost::irange(f,t,s))
#define erng(i,f,t,s) for(int i : boost::irange(f,t+(s>0)-(s<0),s))
#define yes(n) cout<<((n)?YES:NO)<<"\n"
#define Sort(v) sort((v).begin(),(v).end())
#define rSort(v) sort((v).rbegin(),(v).rend())
#define Rev(v) reverse((v).begin(),(v).end())
#define Unique(v) (v).erase(unique((v).begin(),(v).end()),(v).end())
#define inarea(p,a,b) (0<=(p.first)&&0<=(p.second)&&(p.first)<(a)&&(p.second)<(b))
#define in_area(y,x,a,b) (0<=(y)&&0<=(x)&&(y)<(a)&&(x)<(b))
#define in_range(x,a,b) ((a)<=(x)&&(x)<(b))

using namespace std;
using ll    = long long;
using ld    = long double;
using pt    = pair<int, int>;
using ull   = unsigned long long;
using str   = string;
using vbl   = vector<bool>;
using dqbl  = deque<bool>;
using vint  = vector<int>;
using vll   = vector<long long>;
using vdb   = vector<double>;
using vld   = vector<long double>;
using vpt   = vector<pair<int, int>>;
using vstr  = vector<string>;
using vvdb  = vector<vector<double>>;
using vvbl  = vector<vector<bool>>;
using vdqbl = vector<deque<bool>>;
using vvint = vector<vector<int>>;
using vvll  = vector<vector<long long>>;
using Int   = boost::multiprecision::cpp_int;

constexpr int       INF   = 1e9;
constexpr long long LINF  = 1e18;
constexpr double    EPS   = 1e-9;
constexpr int       dy[]  = {1,0,-1,0,1,1,-1,-1};
constexpr int       dx[]  = {0,1,0,-1,-1,1,1,-1};
constexpr pt        dv[]  = { {1,0},{0,1},{-1,0},{0,-1},{1,-1},{1,1},{-1,1},{-1,-1} };

// --- functions for debugging --- //
template<class T>            void observe(const char *n,T &&v)         {cerr<<n<<": "<<v<<"\n";}
template<class S,class... T> void observe(const char *n,S &&v,T&&... w){const char *c=strchr(n+1,',');cerr.write(n,c-n)<<": "<<v<<" |";observe(c+1,w...);}
template<class T> void printv([[maybe_unused]] const char *n, const vector<T> &v){cerr<<"[ ";for(const T &x:v)cerr<<x<<" ";cerr<<"]\n";}
template<class T> void printv([[maybe_unused]] const char *n, const deque<T> &v) {cerr<<"[ ";for(const T &x:v)cerr<<x<<" ";cerr<<"]\n";}
template<class T> void printv([[maybe_unused]] const char *n, const set<T> &v)   {cerr<<"[ ";for(const T &x:v)cerr<<x<<" ";cerr<<"]\n";}
template<class P> void printv([[maybe_unused]] const char *n, const P &p){cerr<<"{ "<<p.first<<" "<<p.second<<" } ";}
template<class T> void printv(const char *n, const vector<vector<T>> &v){bool f=0;for(const vector<T> &x:v){if(f)cerr<<string(strlen(n)+2,' ');f=1;printv<T>("",x);}}
template<class T> void printv(const char *n, const vector<deque<T>> &v) {bool f=0;for(const deque<T> &x:v){if(f)cerr<<string(strlen(n)+2,' ');f=1;printv<T>("",x);}}
template<class S,class T> void printv([[maybe_unused]] const char *n, const map<S,T> &m) {cerr<<"[ ";for(const pair<S,T> &p:m)cerr<<"{ "<<p.first<<", "<<p.second<<" } ";cerr<<"]\n";}
template<class S,class T> void printv([[maybe_unused]] const char *n, const vector<pair<S,T>> &v){cerr<<"[ ";for(const pair<S,T> &p:v)printv<pair<S,T>>("",p);cerr<<"]\n";}
template<class S,class T> void printv([[maybe_unused]] const char *n, const deque<pair<S,T>> &v){cerr<<"[ ";for(const pair<S,T> &p:v)printv<pair<S,T>>("",p);cerr<<"]\n";}
// clang-format on
#pragma endregion

void solve(int N) {
  int ans = 0;

  erng(a, 1, N - 1, 1) {
    ans += N / a;
    ans -= (N % a == 0);
  }

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

// clang-format off
int main() {
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wunused-result"
  int N;
  scanf("%d",&N);
  #pragma GCC diagnostic pop
  solve(N);
  exit(EXIT_SUCCESS);
}


Measured memory_bytes: 3800