#include <bits/stdc++.h>
using namespace std;
inline int read() {
  char ch = getchar();
  int x = 0, f = 1;
  while (ch < '0' || ch > '9') f = ch == '-' ? -1 : 1, ch = getchar();
  while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
  return x * f;
}
const int MAXN = 100010;
int prime[MAXN], primesize = 0;
bool isprime[MAXN];
void get_prime(int n) {
  memset(isprime, true, sizeof(isprime));
  isprime[1] = false;
  for (int i = 2; i <= n; i++) {
    if (isprime[i]) prime[++primesize] = i;
    for (int j = 1; j <= primesize && i * prime[j] <= n; j++) {
      isprime[i * prime[j]] = false;
      if (i % prime[j] == 0) break;
    }
  }
}
bool vis[MAXN];
vector<int> res;
int main(int argc, char *argv[]) {
  ios::sync_with_stdio(false);
  cin.tie(0);
  memset(vis, 0, sizeof(vis));
  res.clear();
  int n = read(), cnt = 0;
  get_prime(n);
  for (int i = (primesize); i >= (1); i -= (1)) {
    int p = prime[i], k = n / p, t = 0;
    for (int j = (1); j <= (k); j += (1))
      if (!vis[p * j]) t++;
    if (t <= 1) continue;
    if (t & 1) {
      for (int j = (1); j <= (k); j += (1))
        if (j != 2 && !vis[p * j]) {
          res.push_back(p * j);
          vis[p * j] = true;
          cnt++;
        }
    } else {
      for (int j = (1); j <= (k); j += (1))
        if (!vis[p * j]) {
          res.push_back(p * j);
          vis[p * j] = true;
          cnt++;
        }
    }
  }
  printf("%d\n", cnt / 2);
  for (int i = (0); i <= ((int)res.size() - 1); i += (1))
    printf("%d%c", res[i], i & 1 ? '\n' : ' ');
  return 0;
}
