#include <bits/stdc++.h>
using namespace std;
const int inf = 2000000000;
static inline int Rint() {
  struct X {
    int dig[256];
    X() {
      for (int i = '0'; i <= '9'; ++i) dig[i] = 1;
      dig['-'] = 1;
    }
  };
  static X fuck;
  int s = 1, v = 0, c;
  for (; !fuck.dig[c = getchar()];)
    ;
  if (c == '-')
    s = 0;
  else if (fuck.dig[c])
    v = c ^ 48;
  for (; fuck.dig[c = getchar()]; v = v * 10 + (c ^ 48))
    ;
  return s ? v : -v;
}
template <typename T>
static inline void cmax(T& a, const T& b) {
  if (b > a) a = b;
}
template <typename T>
static inline void cmin(T& a, const T& b) {
  if (b < a) a = b;
}
const int maxn = 100005;
int mask[maxn];
int used[maxn];
int is_prime[maxn];
int cmp(int x, int y) { return mask[x] > mask[y]; }
int main() {
  const int n = Rint();
  fill(is_prime, is_prime + n + 1, 1);
  for (int i = 2; i <= n; ++i)
    if (is_prime[i] == 1) {
      for (int j = i + i; j <= n; j += i) is_prime[j] = 0, ++mask[j];
      mask[i] = 1;
    }
  vector<int> ans;
  for (int i = n; i >= 2; --i)
    if (is_prime[i] == 1) {
      vector<int> adj;
      for (int j = i; j <= n; j += i)
        if (used[j] == 0) {
          adj.push_back(j);
        }
      const int size = ((int)(adj).size());
      if (size % 2 == 0) {
        for (int j = 0; j < size; j += 2) {
          ans.push_back(adj[j]), ans.push_back(adj[j + 1]);
          used[adj[j]] = 1;
          used[adj[j + 1]] = 1;
        }
      } else {
        sort((adj).begin(), (adj).end(), cmp);
        for (int j = 1; j < size; j += 2) {
          ans.push_back(adj[j]), ans.push_back(adj[j + 1]);
          used[adj[j]] = 1;
          used[adj[j + 1]] = 1;
        }
      }
    }
  printf("%d\n", ans.size() / 2);
  for (int i = 0; i < ans.size(); i += 2) printf("%d %d\n", ans[i], ans[i + 1]);
  return 0;
}
