#include <bits/stdc++.h>

/*** TEMPLATE CODE STARTS HERE ***/

using namespace std;

typedef vector<int> vi;
typedef vector<string> vs;
typedef long long ll;
typedef complex<double> pnt;
typedef pair<int, int> pii;

#define RA(x) begin(x), end(x)
#define FE(i, x) for (auto i = begin(x); i != end(x); ++i)
#define SZ(x) ((int) (x).size())

template<class T>
void splitstr(const string &s, vector<T> &out)
{
    istringstream in(s);
    out.clear();
    copy(istream_iterator<T>(in), istream_iterator<T>(), back_inserter(out));
}

template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }

static void redirect(int argc, const char **argv)
{
    ios::sync_with_stdio(false);
    if (argc > 1)
    {
        static filebuf f;
        f.open(argv[1], ios::in);
        cin.rdbuf(&f);
        if (!cin)
        {
            cerr << "Failed to open '" << argv[1] << "'" << endl;
            exit(1);
        }
    }

    if (argc > 2)
    {
        static filebuf f;
        f.open(argv[2], ios::out | ios::trunc);
        cout.rdbuf(&f);
        if (!cout)
        {
            cerr << "Failed to open '" << argv[2] << "'" << endl;
        }
    }
}

/*** TEMPLATE CODE ENDS HERE */

static vector<int> primes;

static void make_primes(int N)
{
    vector<bool> comp(N + 1);
    for (int i = 2; i <= N; i++)
        if (!comp[i])
        {
            for (int j = i * 2; j <= N; j += i)
                comp[j] = true;
            primes.push_back(i);
        }
}

int main(int argc, const char **argv)
{
    redirect(argc, argv);

    int N;
    cin >> N;
    make_primes(N);
    reverse(RA(primes));
    vector<bool> used(N + 1);
    vector<pii> ans;
    for (int p : primes)
    {
        if (2 * p > N)
            continue;

        int have = 0;
        bool save = false;
        for (int i = p; i <= N; i += p)
            if (!used[i])
                have++;
        if ((have & 1) && (p != 2))
            save = true;
        if (save)
        {
            assert(!used[2 * p]);
            used[2 * p] = true;
            have--;
        }

        int last = -1;
        for (int i = p; i <= N; i += p)
            if (!used[i])
            {
                if (last == -1)
                    last = i;
                else
                {
                    ans.emplace_back(last, i);
                    last = -1;
                }
            }

        if (save)
            used[2 * p] = false;
    }

    cout << ans.size() << '\n';
    for (const auto &a : ans)
        cout << a.first << ' ' << a.second << '\n';
    return 0;
}


#include <bits/stdc++.h>

/*** TEMPLATE CODE STARTS HERE ***/

using namespace std;

typedef vector<int> vi;
typedef vector<string> vs;
typedef long long ll;
typedef complex<double> pnt;
typedef pair<int, int> pii;

#define RA(x) begin(x), end(x)
#define FE(i, x) for (auto i = begin(x); i != end(x); ++i)
#define SZ(x) ((int) (x).size())

template<class T>
void splitstr(const string &s, vector<T> &out)
{
    istringstream in(s);
    out.clear();
    copy(istream_iterator<T>(in), istream_iterator<T>(), back_inserter(out));
}

template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }

static void redirect(int argc, const char **argv)
{
    ios::sync_with_stdio(false);
    if (argc > 1)
    {
        static filebuf f;
        f.open(argv[1], ios::in);
        cin.rdbuf(&f);
        if (!cin)
        {
            cerr << "Failed to open '" << argv[1] << "'" << endl;
            exit(1);
        }
    }

    if (argc > 2)
    {
        static filebuf f;
        f.open(argv[2], ios::out | ios::trunc);
        cout.rdbuf(&f);
        if (!cout)
        {
            cerr << "Failed to open '" << argv[2] << "'" << endl;
        }
    }
}

/*** TEMPLATE CODE ENDS HERE */

static vector<int> primes;

static void make_primes(int N)
{
    vector<bool> comp(N + 1);
    for (int i = 2; i <= N; i++)
        if (!comp[i])
        {
            for (int j = i * 2; j <= N; j++)
                comp[j] = true;
            primes.push_back(i);
        }
}

int main(int argc, const char **argv)
{
    redirect(argc, argv);

    int N;
    cin >> N;
    make_primes(N);
    reverse(RA(primes));
    vector<bool> used(N + 1);
    vector<pii> ans;
    for (int p : primes)
    {
        if (2 * p > N)
            continue;

        int have = 0;
        bool save = false;
        for (int i = p; i <= N; i += p)
            if (!used[i])
                have++;
        if ((have & 1) && (p != 2))
            save = true;
        if (save)
        {
            assert(!used[2 * p]);
            used[2 * p] = true;
            have--;
        }

        int last = -1;
        for (int i = p; i <= N; i += p)
            if (!used[i])
            {
                if (last == -1)
                    last = i;
                else
                {
                    ans.emplace_back(last, i);
                    last = -1;
                }
            }

        if (save)
            used[2 * p] = false;
    }

    cout << ans.size() << '\n';
    for (const auto &a : ans)
        cout << a.first << ' ' << a.second << '\n';
    return 0;
}


#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<set>
#include<stack>
#include<cmath>
#include <map>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cassert>
using namespace std;

#define DEBUG //on-off switch for prlling statements

// Input macros
#define s(n)                        scanf("%d",&n)
#define sc(n)                       scanf("%c",&n)
#define sl(n)                       scanf("%lld",&n)
#define sf(n)                       scanf("%lf",&n)
#define ss(n)                       scanf("%s",n)

// Useful constants
#define EPS                         1e-5

// Useful hardware instructions
#define bitcount1                    __builtin_popcount1
#define gcd                         __gcd

// Useful container manipulation / traversal macros
#define forall(i,a,b)               for(ll i=a;i<b;i++)
#define foreach(v, c)               for( typeof( (c).begin()) v = (c).begin();  v != (c).end(); ++v)
#define all(a)                      a.begin(), a.end()
#define in(a,b)                     ( (b).find(a) != (b).end())
#define pb                          push_back
#define fill(a,v)                    memset(a, v, sizeof a)
#define sz(a)                       ((ll)(a.size()))

// Some common useful functions
#define miN(a,b)                     ( (a) < (b) ? (a) : (b))
#define maX(a,b)                     ( (a) > (b) ? (a) : (b))

#define ll long long int
#define llu long long unsigned
#define ld long
#define INF 500000000
#define pii pair<int,int>
#define mod 1000000007
vector<ll> pri;
vector<pii> ans;
int vis[1000001];
int main()
{
    int n;
    fill(vis,0);
    s(n);
    int pr=2;
    int flag=0;
    while(1)
    {
        flag=0;
        pri.pb(pr);
        for(int i=2*pr;i<=n;i+=pr)
        {
            vis[i]=1;
        }
        for(int i=pr+1;i<=n;i++)
        {
            if(!vis[i])
            {
                pr=i;
                flag=1;
                break;
            }
        }
        if(flag == 0)
        break;
    }
    fill(vis,0);
    for(int i=pri.size()-1;i>=0;i--)
    {
        int val=pri[i];
        flag=0;
        for(ll j=pri[i]*pri[i];j<=n;j=j*pri[i])
        {
            if(flag == 1)
            {
                val=j;
                flag=0;
                continue;
            }
            ans.pb(make_pair(val,j));
            vis[val]=vis[j]=1;
            flag=1;
        }
        for(int j=pri[i]*3;j<=n;j+=pri[i])
        {
            if(!vis[j])
            {
                if(flag == 1)
                {
                    val=j;
                    flag=0;
                    continue;
                }
                ans.pb(make_pair(val,j));
                vis[val]=vis[j]=1;
                flag=1;
            }
        }
        if(!vis[pri[i]*2] && pri[i]*2 <=n)
        if(flag == 0)
        {
            ans.pb(make_pair(val,pri[i]*2));
            vis[val]=vis[pri[i]*2]=1;
        }
    }
    cout<<ans.size()<<endl;
    for(int i=0;i<ans.size();i++)
    cout<<ans[i].first<<" "<<ans[i].second<<endl;
}


#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<set>
#include<stack>
#include<cmath>
#include <map>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cassert>
using namespace std;

#define DEBUG //on-off switch for prlling statements

// Input macros
#define s(n)                        scanf("%d",&n)
#define sc(n)                       scanf("%c",&n)
#define sl(n)                       scanf("%lld",&n)
#define sf(n)                       scanf("%lf",&n)
#define ss(n)                       scanf("%s",n)

// Useful constants
#define EPS                         1e-5

// Useful hardware instructions
#define bitcount1                    __builtin_popcount1
#define gcd                         __gcd

// Useful container manipulation / traversal macros
#define forall(i,a,b)               for(ll i=a;i<b;i++)
#define foreach(v, c)               for( typeof( (c).begin()) v = (c).begin();  v != (c).end(); ++v)
#define all(a)                      a.begin(), a.end()
#define in(a,b)                     ( (b).find(a) != (b).end())
#define pb                          push_back
#define fill(a,v)                    memset(a, v, sizeof a)
#define sz(a)                       ((ll)(a.size()))

// Some common useful functions
#define miN(a,b)                     ( (a) < (b) ? (a) : (b))
#define maX(a,b)                     ( (a) > (b) ? (a) : (b))

#define ll long long int
#define llu long long unsigned
#define ld long
#define INF 500000000
#define pii pair<int,int>
#define mod 1000000007
vector<ll> pri;
vector<pii> ans;
int vis[1000001];
int main()
{
    int n;
    fill(vis,0);
    s(n);
    int pr=2;
    int flag=0;
    while(1)
    {
        flag=0;
        pri.pb(pr);
        for(int i=2*pr;i<=n;i+=pr)
        {
            vis[i]=1;
        }
        for(int i=pr+1;i<=n;i++)
        {
            if(!vis[i])
            {
                pr=i;
                flag=1;
                break;
            }
        }
        if(flag == 0)
        break;
    }
    fill(vis,0);
    for(int i=pri.size()-1;i>=0;i--)
    {
        int val=pri[i];
        flag=0;
        vector<int> tmp;
        for(int j=pri[i]*2;j<=n;j+=pri[i])
        {
            if(!vis[j])
            tmp.pb(j);
        }
        for(int j=tmp.size()-1;j>=0;j--)
        {
            if(flag == 0)
            {
                ans.pb(make_pair(tmp[j],val));
                vis[tmp[j]]=vis[val]=1;
                flag=1;
            }
            else
            {
                val=tmp[j];
                flag=0;
            }
        }
    }
    cout<<ans.size()<<endl;
    for(int i=0;i<ans.size();i++)
    cout<<ans[i].first<<" "<<ans[i].second<<endl;
}


#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<set>
#include<stack>
#include<cmath>
#include <map>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cassert>
using namespace std;

#define DEBUG //on-off switch for prlling statements

// Input macros
#define s(n)                        scanf("%d",&n)
#define sc(n)                       scanf("%c",&n)
#define sl(n)                       scanf("%lld",&n)
#define sf(n)                       scanf("%lf",&n)
#define ss(n)                       scanf("%s",n)

// Useful constants
#define EPS                         1e-5

// Useful hardware instructions
#define bitcount1                    __builtin_popcount1
#define gcd                         __gcd

// Useful container manipulation / traversal macros
#define forall(i,a,b)               for(ll i=a;i<b;i++)
#define foreach(v, c)               for( typeof( (c).begin()) v = (c).begin();  v != (c).end(); ++v)
#define all(a)                      a.begin(), a.end()
#define in(a,b)                     ( (b).find(a) != (b).end())
#define pb                          push_back
#define fill(a,v)                    memset(a, v, sizeof a)
#define sz(a)                       ((ll)(a.size()))

// Some common useful functions
#define miN(a,b)                     ( (a) < (b) ? (a) : (b))
#define maX(a,b)                     ( (a) > (b) ? (a) : (b))

#define ll long long int
#define llu long long unsigned
#define ld long
#define INF 500000000
#define pii pair<int,int>
#define mod 1000000007
vector<int> pri;
vector<pii> ans;
int vis[100001];
int main()
{
    int n;
    fill(vis,0);
    s(n);
    int pr=2;
    int flag=0;
    while(1)
    {
        flag=0;
        pri.pb(pr);
        for(int i=2*pr;i<=n;i+=pr)
        {
            vis[i]=1;
        }
        for(int i=pr+1;i<=n;i++)
        {
            if(!vis[i])
            {
                pr=i;
                flag=1;
                break;
            }
        }
        if(flag == 0)
        break;
    }
    fill(vis,0);
    for(int i=0;i<pri.size();i++)
    {
        int val=pri[i];
        flag=0;
        for(int j=pri[i]*2;j<=n;j+=pri[i])
        {
            if(!vis[j])
            {
                if(flag == 1)
                {
                    val=j;
                    flag=0;
                    continue;
                }
                ans.pb(make_pair(val,j));
                vis[val]=vis[j]=1;
                flag=1;
            }
        }
    }
    cout<<ans.size()<<endl;
    for(int i=0;i<ans.size();i++)
    cout<<ans[i].first<<" "<<ans[i].second<<endl;
}


#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<set>
#include<stack>
#include<cmath>
#include <map>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cassert>
using namespace std;

#define DEBUG //on-off switch for prlling statements

// Input macros
#define s(n)                        scanf("%d",&n)
#define sc(n)                       scanf("%c",&n)
#define sl(n)                       scanf("%lld",&n)
#define sf(n)                       scanf("%lf",&n)
#define ss(n)                       scanf("%s",n)

// Useful constants
#define EPS                         1e-5

// Useful hardware instructions
#define bitcount1                    __builtin_popcount1
#define gcd                         __gcd

// Useful container manipulation / traversal macros
#define forall(i,a,b)               for(ll i=a;i<b;i++)
#define foreach(v, c)               for( typeof( (c).begin()) v = (c).begin();  v != (c).end(); ++v)
#define all(a)                      a.begin(), a.end()
#define in(a,b)                     ( (b).find(a) != (b).end())
#define pb                          push_back
#define fill(a,v)                    memset(a, v, sizeof a)
#define sz(a)                       ((ll)(a.size()))

// Some common useful functions
#define miN(a,b)                     ( (a) < (b) ? (a) : (b))
#define maX(a,b)                     ( (a) > (b) ? (a) : (b))

#define ll long long int
#define llu long long unsigned
#define ld long
#define INF 500000000
#define pii pair<int,int>
#define mod 1000000007
vector<ll> pri;
vector<pii> ans;
int vis[1000001];
int main()
{
    int n;
    fill(vis,0);
    s(n);
    int pr=2;
    int flag=0;
    while(1)
    {
        flag=0;
        pri.pb(pr);
        for(int i=2*pr;i<=n;i+=pr)
        {
            vis[i]=1;
        }
        for(int i=pr+1;i<=n;i++)
        {
            if(!vis[i])
            {
                pr=i;
                flag=1;
                break;
            }
        }
        if(flag == 0)
        break;
    }
    fill(vis,0);
    for(int i=pri.size()-1;i>=0;i--)
    {
        int val=pri[i];
        flag=0;
        for(ll j=pri[i]*pri[i];j<=n;j=j*pri[i])
        {
            if(flag == 1)
            {
                val=j;
                flag=0;
                continue;
            }
            ans.pb(make_pair(val,j));
            vis[val]=vis[j]=1;
            flag=1;
        }
        for(int j=pri[i]*2;j<=n;j+=pri[i])
        {
            if(!vis[j])
            {
                if(flag == 1)
                {
                    val=j;
                    flag=0;
                    continue;
                }
                ans.pb(make_pair(val,j));
                vis[val]=vis[j]=1;
                flag=1;
            }
        }
    }
    cout<<ans.size()<<endl;
    for(int i=0;i<ans.size();i++)
    cout<<ans[i].first<<" "<<ans[i].second<<endl;
}


#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<set>
#include<stack>
#include<cmath>
#include <map>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cassert>
using namespace std;

#define DEBUG //on-off switch for prlling statements

// Input macros
#define s(n)                        scanf("%d",&n)
#define sc(n)                       scanf("%c",&n)
#define sl(n)                       scanf("%lld",&n)
#define sf(n)                       scanf("%lf",&n)
#define ss(n)                       scanf("%s",n)

// Useful constants
#define EPS                         1e-5

// Useful hardware instructions
#define bitcount1                    __builtin_popcount1
#define gcd                         __gcd

// Useful container manipulation / traversal macros
#define forall(i,a,b)               for(ll i=a;i<b;i++)
#define foreach(v, c)               for( typeof( (c).begin()) v = (c).begin();  v != (c).end(); ++v)
#define all(a)                      a.begin(), a.end()
#define in(a,b)                     ( (b).find(a) != (b).end())
#define pb                          push_back
#define fill(a,v)                    memset(a, v, sizeof a)
#define sz(a)                       ((ll)(a.size()))

// Some common useful functions
#define miN(a,b)                     ( (a) < (b) ? (a) : (b))
#define maX(a,b)                     ( (a) > (b) ? (a) : (b))

#define ll long long int
#define llu long long unsigned
#define ld long
#define INF 500000000
#define pii pair<int,int>
#define mod 1000000007
vector<int> pri;
vector<pii> ans;
int vis[100001];
int main()
{
    int n;
    fill(vis,0);
    s(n);
    int pr=2;
    int flag=0;
    while(1)
    {
        flag=0;
        pri.pb(pr);
        for(int i=2*pr;i<=n;i+=pr)
        {
            vis[i]=1;
        }
        for(int i=pr+1;i<=n;i++)
        {
            if(!vis[i])
            {
                pr=i;
                flag=1;
                break;
            }
        }
        if(flag == 0)
        break;
    }
    fill(vis,0);
    for(int i=pri.size()-1;i>=0;i--)
    {
        int val=pri[i];
        flag=0;
        for(int j=pri[i]*pri[i];j<=n;j=j*pri[i])
        {
            if(flag == 1)
            {
                val=j;
                flag=0;
                continue;
            }
            ans.pb(make_pair(val,j));
            vis[val]=vis[j]=1;
            flag=1;
        }
        for(int j=pri[i]*2;j<=n;j+=pri[i])
        {
            if(!vis[j])
            {
                if(flag == 1)
                {
                    val=j;
                    flag=0;
                    continue;
                }
                ans.pb(make_pair(val,j));
                vis[val]=vis[j]=1;
                flag=1;
            }
        }
    }
    cout<<ans.size()<<endl;
    for(int i=0;i<ans.size();i++)
    cout<<ans[i].first<<" "<<ans[i].second<<endl;
}


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#include<string>
#include<queue>
#include<list>
#include<iomanip>
#include<limits>
#include<typeinfo>
#include<functional>
#include<numeric>
#include<unordered_set>
#include<unordered_map>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;

#define X first
#define Y second

const int MaxN=100010;

int n;
int b[MaxN],u[MaxN];
vector<int> p;
vector<pii> ans;

void answer(int x,int y)
{
	ans.push_back(pii(x,y));
	u[x]=u[y]=1;
}

int main()
{
	cin>>n;
	for (int i=2;i<=n;++i)
		if (!b[i])
		{
			p.push_back(i);
			vector<int> q;
			for (int j=i;j<=n;j+=i)
			{
				b[j]=1;
				if (!u[j]) q.push_back(j);
			}
			if (i==2) continue;
			if (q.size()==1) continue;
			if (q.size()%2)
				q.erase(q.begin()+1,q.begin()+2);
			for (int i=0;i<q.size()/2;++i)
				answer(q[i*2],q[i*2+1]);
		}
	p.clear();
	for (int i=2;i<=n;i+=2)
		if (!u[i]) p.push_back(i);
	for (int i=0;i<p.size()/2;++i)
		answer(p[i*2],p[i*2+1]);
	cout<<ans.size()<<endl;
	for (auto x : ans)
		printf("%d %d\n",x.X,x.Y);
	return 0;
}


#include <bits/stdc++.h>
#ifdef ONLINE_JUDGE
    #define out(x)
#else
    #define out(x) cerr<<#x"="<<(x)<<endl
#endif
using namespace std;
typedef long long LL;
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef vector<pii> vpii;
#define REP(i,n) for(int i=0; i<int(n); i++)
#define pb push_back
#define mp make_pair
#define X first
#define Y second
vi f[112345];
bool used[112345];
vi p;
int main(){
    int n;
    scanf("%d",&n);
    for(int i=2; i<=n; ++i){
        if(f[i].size()==0){
            p.pb(i);
            for(int j=i; j<=n; j+=i)
                f[j].pb(i);
        }
    }
    reverse(p.begin(), p.end());
    vpii ans;
    for(auto x: p){
        vpii tmp;
        for(int i=x; i<=n; i+=x)
            if(!used[i])tmp.pb(mp(f[i].size(), i));
        sort(tmp.begin(), tmp.end());
        reverse(tmp.begin(), tmp.end());
        while(tmp.size()>=2){
            int u=tmp.back().Y; tmp.pop_back();
            int v=tmp.back().Y; tmp.pop_back();
            used[u]=used[v]=1;
            ans.pb(mp(u,v));
        }
        if(tmp.size()){
            int u=tmp.back().Y;
            f[u].pop_back();
        }
    }
    printf("%d\n", ans.size());
    for(auto x: ans)
        printf("%d %d\n", x.X, x.Y);
}


#include "assert.h"
#include <algorithm>
#include <bitset>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <time.h>
#include <vector>

#if LOCAL
	#define DO_NOT_SEND
#endif

typedef long long LL;

int IntMaxVal = (int) 1e20;
int IntMinVal = (int) -1e20;
LL LongMaxVal = (LL) 1e20;
LL LongMinVal = (LL) -1e20;

#define FOR(i, a, b) for(int i = a; i < b ; ++i)
#define FORD(i, a, b) for(int i = a; i >= b; --i)

template<typename T> inline void minimize(T &a, T b) { a = std::min(a, b); }
template<typename T> inline void maximize(T &a, T b) { a = std::max(a, b); }

#define all(v) v.begin(),v.end()

using namespace std;

#define endl '\n'
template<typename T> struct argument_type;
template<typename T, typename U> struct argument_type<T(U)> { typedef U type; };
#define next(t, i) argument_type<void(t)>::type i; cin >> i;
#define nextVector(t, v, size) vector< argument_type<void(t)>::type > v(size); { for (int i = 0 ; i < size ; i++) cin >> v[i]; }

#define range(name, start, count) vector<int> name(count); { for (int i = 0 ; i < count ; i++) name[i] = i + start; }

template <typename T1, typename T2> istream& operator >>(istream& is, pair<T1, T2>& s) { is >> s.first >> s.second; return is; }
template <typename T> ostream& operator << (ostream& os, const vector<T> &v) { for (int i = 0 ; i < v.size() ; i++) os << v[i] << ' '; os << endl; return os; }
template <typename T1, typename T2> ostream& operator <<(ostream& s, pair<T1, T2>& t) { s << t.first << ' ' << t.second; return s; }
template <typename T> vector<T> readVector(int n) { vector<T> res(n); for (int i = 0 ; i < n ; i++) cin >> res[i]; return res; }

vector<int> get_primes(int n) {
	vector<bool> isp(n, true);
	vector<int> res;
	FOR (i, 2, n) if (isp[i]) {
		for (LL k = 1LL * i * i ; k < n ; k += i) isp[k] = false;
		res.push_back(i);
	}
	return res;
}

int main() {
	srand (time(NULL));
	ios_base::sync_with_stdio(false); cin.tie(NULL);

	next(int, n);

	auto ps = get_primes(n + 1);

	set<int> nums;
	FOR (i, 2, n + 1) nums.insert(i);

	for (auto p : ps) if (2 * p > n) nums.erase(p);

	cout << nums.size() / 2 << endl;

	reverse(all(ps));
	for (auto p : ps) {
		vector<int> numsThis;
		for (int x = p ; x <= n ; x += p) if (nums.count(x)) {
			nums.erase(x);
			numsThis.push_back(x);
		}
		if (numsThis.empty()) continue;

		if (numsThis.size() % 2) {
			int popped = numsThis[1];
			assert(popped % 2 == 0);
			nums.insert(popped);
			numsThis[1] = numsThis.back();
			numsThis.pop_back();
		}
		FOR (i, 1, numsThis.size()) {
			cout << numsThis[i - 1] << ' ' << numsThis[i] << endl;
			i++;
		}
	}
}


#include <algorithm>
#include <bitset>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <set>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <time.h>
#include <vector>

#if LOCAL
	#define DO_NOT_SEND
#endif

typedef long long LL;

int IntMaxVal = (int) 1e20;
int IntMinVal = (int) -1e20;
LL LongMaxVal = (LL) 1e20;
LL LongMinVal = (LL) -1e20;

#define FOR(i, a, b) for(int i = a; i < b ; ++i)
#define FORD(i, a, b) for(int i = a; i >= b; --i)

template<typename T> inline void minimize(T &a, T b) { a = std::min(a, b); }
template<typename T> inline void maximize(T &a, T b) { a = std::max(a, b); }

#define all(v) v.begin(),v.end()

using namespace std;

#define endl '\n'
template<typename T> struct argument_type;
template<typename T, typename U> struct argument_type<T(U)> { typedef U type; };
#define next(t, i) argument_type<void(t)>::type i; cin >> i;
#define nextVector(t, v, size) vector< argument_type<void(t)>::type > v(size); { for (int i = 0 ; i < size ; i++) cin >> v[i]; }

#define range(name, start, count) vector<int> name(count); { for (int i = 0 ; i < count ; i++) name[i] = i + start; }

template <typename T1, typename T2> istream& operator >>(istream& is, pair<T1, T2>& s) { is >> s.first >> s.second; return is; }
template <typename T> ostream& operator << (ostream& os, const vector<T> &v) { for (int i = 0 ; i < v.size() ; i++) os << v[i] << ' '; os << endl; return os; }
template <typename T1, typename T2> ostream& operator <<(ostream& s, pair<T1, T2>& t) { s << t.first << ' ' << t.second; return s; }
template <typename T> vector<T> readVector(int n) { vector<T> res(n); for (int i = 0 ; i < n ; i++) cin >> res[i]; return res; }

int main() {
	srand (time(NULL));
    ios_base::sync_with_stdio(false); cin.tie(NULL);

	next(int, n);

	vector<pair<int, int>> res;

	vector<bool> taken(n + 1);
	FOR (i, 2, n + 1) {
		vector<int> cur;
		for (int j = i ; j <= n ; j += i) if (!taken[j]) cur.push_back(j);

		FOR (j, 1, cur.size()) {
			res.push_back(make_pair(cur[j - 1], cur[j]));
			taken[cur[j - 1]] = true;
			taken[cur[j - 0]] = true;
			j++;
		}
	}

	cout << res.size() << endl;
	for (auto p : res) cout << p << endl;
}


#include <bits/stdc++.h>
#include <stack>
#include <cassert>
#include <set>
#include <queue>
#include <iostream>
#include <vector>
#include <complex>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <map>
#include <cmath>
#include <numeric>

using namespace std;
typedef long long ll;
typedef pair<int,int> PI;
const double EPS=1e-6;
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define F first
#define S second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define SZ(a) (int)((a).size())
#define ALL(a) (a).begin(),(a).end()
#define RALL(a) a.rbegin(),a.rend()
#define FLL(a,b) memset((a),b,sizeof(a))
#define CLR(a) FLL(a,0)
#define declare(a,it) __typeof(a) it=(a)
#define FOR(it,a) for(declare(a.begin(),it);it!=a.end();++it)
#define FORR(it,a) for(declare(a.rbegin(),it);it!=a.rend();++it)
template<class T,class U> ostream& operator<< (ostream& o, const pair<T,U>& v){return o << "(" << v.F << ", " << v.S << ")";}
template<class T> ostream& operator<< (ostream& o, const vector<T>& v){o << "{";rep(i,SZ(v)) o << (i?", ":"") << v[i];return o << "}";}
void pkuassert(bool t){t=1/t;};
int dx[]={0,1,0,-1,1,1,-1,-1};
int dy[]={1,0,-1,0,-1,1,1,-1};
int s2i(string& a){stringstream ss(a);int r;ss>>r;return r;}

bool use[110000];

bool npr[110000];

int main(int argc, char *argv[])
{
  for(int i = 2; i < 110000; ++i){
    if(npr[i]) continue;
    for(int j = 2*i; j < 110000; j += i)
      npr[j] = 1;
  }

  int n;
  cin >> n;

  vector<PI> ans;
  for(int i=n;i>1;--i){
    if(npr[i]) continue;
    vector<int> re;
    for(int j=1;j*i<=n;++j){
      if(use[j*i]) continue;
      re.push_back(j*i);
    }

    for(int i = 1; i < (int)re.size();){
      PI pa;
      use[re[i-1]] = 1;
      pa.first = re[i-1];
      if(i==1 && re.size()%2==1) ++i;
      use[re[i]] = 1;
      pa.second = re[i];
      ans.push_back(pa);
      i+=2;
    }
  }

  cout << ans.size() << endl;
  for(auto e: ans)
    cout << e.first << " " << e.second << endl;

  return 0;
}


#include<bits/stdc++.h>
#include <complex>
#include <numeric>
#include <stack>
#include <map>
#include <queue>
#include <cstdio>
#include <iostream>
#include <set>
#include <vector>
#include <algorithm>
#include <string>
#include <cstring>
#include <cmath>

using namespace std;
typedef long long ll;
#define rep(i,n) for(int i=0;i<n;++i)
#define FOR(it,in) for(__typeof(in.begin())it=in.begin();it!=in.end();++it)
#define pb(a) push_back(a)
#define mp make_pair
#define ALL(a) a.begin(),a.end()
#define SZ(a) (int)(a.size())
#define F first
#define S second
int dx[] = {0,1,0,-1};
int dy[] = {1,0,-1,0};
#define absll(a) ((a)>0?(a):-(a))

typedef pair<int,int> PI;
typedef long long ll;

int use[1<<20];

int npr[1<<20];

int main(int argc, char *argv[])
{
  int n;
  cin >> n;

  for(int i = 2; i<100000;++i){
    if(npr[i]) continue;
    for(int  j = 2*i;j<100000;j+=i)
      npr[j] = 1;
  }

  vector<PI> ans;

  for(int i = n; i>1; --i){
    if(use[i] || npr[i]) continue;
    vector<int> app;
    for(int j = i; j <=n; j+=i){
      if(use[j]) continue;
      app.push_back(j);
    }
    for(int k=0;k+1<SZ(app);k+=2){
      use[app[k]] = 1;
      use[app[k+1]] = 1;
      ans.push_back({app[k],app[k+1]});
    }
  }

  cout << ans.size() << endl;
  for(auto e : ans)
    cout << e.first << " " << e.second << endl;

  return 0;
}


#include<bits/stdc++.h>
#include <complex>
#include <numeric>
#include <stack>
#include <map>
#include <queue>
#include <cstdio>
#include <iostream>
#include <set>
#include <vector>
#include <algorithm>
#include <string>
#include <cstring>
#include <cmath>

using namespace std;
typedef long long ll;
#define rep(i,n) for(int i=0;i<n;++i)
#define FOR(it,in) for(__typeof(in.begin())it=in.begin();it!=in.end();++it)
#define pb(a) push_back(a)
#define mp make_pair
#define ALL(a) a.begin(),a.end()
#define SZ(a) (int)(a.size())
#define F first
#define S second
int dx[] = {0,1,0,-1};
int dy[] = {1,0,-1,0};
#define absll(a) ((a)>0?(a):-(a))

typedef pair<int,int> PI;
typedef long long ll;

int use[1<<20];

int main(int argc, char *argv[])
{
  int n;
  cin >> n;

  vector<PI> ans;

  for(int i = 2; i<=n; ++i){
    if(use[i]) continue;
    vector<int> app;
    for(int j = i; j <=n; j+=i){
      if(use[j]) continue;
      app.push_back(j);
    }
    for(int k=0;k+1<SZ(app);k+=2){
      use[app[k]] = 1;
      use[app[k+1]] = 1;
      ans.push_back({app[k],app[k+1]});
    }
  }

  cout << ans.size() << endl;
  for(auto e : ans)
    cout << e.first << " " << e.second << endl;

  return 0;
}


#define y1 JulioCortasar
#define y2 GabrielGarciaMarquez
#include <cmath>
#undef y1
#undef y2

#include <ctime>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>

#include <algorithm>
#include <iostream>
#include <vector>
#include <string>

#include <bitset>
#include <queue>
#include <deque>
#include <stack>
#include <tuple>
#include <set>
#include <map>

#ifdef LOCAL
    #define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
    #define eprintf(...) 42
#endif

#define pb push_back
#define mp make_pair

using namespace std;

typedef long long ll;
typedef long double lf;
typedef pair<int, int> pii;

void initrand()
{
    ll seed;
    asm("rdtsc":"=A"(seed));
    srand(seed);
}

const int maxn = 100000;

int used[maxn + 1], n;

int main()
{
#ifdef LOCAL
	freopen("input.txt", "r", stdin);
#endif
    ios_base::sync_with_stdio(false);
    cin >> n;
    fill(used, used + n + 1, 0);
    vector<int> rest;
    vector<pii> ans;
    for (int i = 3; i <= n / 2; ++i)
    {
        if (used[i] || (i % 2 == 0)) continue;
        vector<int> v;
        for (int j = i; j <= n; j += i)
            if (!used[j])
            {
                v.pb(j);
                used[j] = 1;
            }
        assert(v.size() > 1);
        if (v.size() & 1)
        {
            rest.pb(v[1]);
            v.erase(v.begin() + 1);
        }
        for (size_t j = 0; j < v.size(); j += 2)
            ans.pb(pii(v[j], v[j + 1]));
    }
    for (int i = 2; i <= n; i += 2)
        if (!used[i]) rest.pb(i);
    for (size_t i = 0; i + 1 < rest.size(); i += 2)
        ans.pb(pii(rest[i], rest[i + 1]));
    cout << ans.size() << endl;
    for (pii cur : ans)
        cout << cur.first << ' ' << cur.second << '\n';
#ifdef LOCAL
    cerr << "Time = " << clock() / 1000 << " ms." << endl;
#endif
	return 0;
}


#define y1 JulioCortasar
#define y2 GabrielGarciaMarquez
#include <cmath>
#undef y1
#undef y2

#include <ctime>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>

#include <algorithm>
#include <iostream>
#include <vector>
#include <string>

#include <bitset>
#include <queue>
#include <deque>
#include <stack>
#include <tuple>
#include <set>
#include <map>

#ifdef LOCAL
    #define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
    #define eprintf(...) 42
#endif

#define pb push_back
#define mp make_pair

using namespace std;

typedef long long ll;
typedef long double lf;
typedef pair<int, int> pii;

void initrand()
{
    ll seed;
    asm("rdtsc":"=A"(seed));
    srand(seed);
}

const int maxn = 100000;

int used[maxn + 1], n;

int main()
{
#ifdef LOCAL
	freopen("input.txt", "r", stdin);
#endif
    ios_base::sync_with_stdio(false);
    cin >> n;
    fill(used, used + n + 1, 0);
    vector<int> rest;
    vector<pii> ans;
    for (int i = 3; i <= n / 2; ++i)
    {
        if (used[i]) continue;
        vector<int> v;
        for (int j = i; j <= n; j += i)
            if (!used[j]) v.pb(j), used[j] = 1;
        if (v.size() & 1)
            rest.pb(v[1]), v.erase(v.begin() + 1);
        for (size_t j = 0; j < v.size(); j += 2)
            ans.pb(pii(v[j], v[j + 1]));
    }
    for (int i = 2; i <= n; i += 2)
        if (!used[i]) rest.pb(i), used[i] = 1;
    for (size_t i = 0; i + 1 < rest.size(); ++i)
        ans.pb(pii(rest[i], rest[i + 1]));
    cout << ans.size() << endl;
    for (pii cur : ans)
        cout << cur.first << ' ' << cur.second << '\n';
#ifdef LOCAL
    cerr << "Time = " << clock() / 1000 << " ms." << endl;
#endif
	return 0;
}


#include <iostream>
#include <iomanip>
#include <algorithm>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <cassert>
#include <functional>

#define pb push_back
#define mp make_pair

using namespace std;

int n;
bool primes[111111], used[111111];
vector<pair<int, int> > ans;

int main() {
#ifndef ONLINE_JUDGE
	//freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i=2; i<1200; i++) if (!primes[i]) for (int j=i*2; j<111111; j+=i) primes[j]=true;
	for (int i=n/2; i>=2; i--) if (!primes[i]) {
		vector<int> v;
		for (int j=i; j<=n; j+=i) if (!used[j]&&j!=2*i) v.pb(j);
		for (int j=0; j<v.size()-1; j+=2) ans.pb(mp(v[j], v[j+1])), used[v[j]]=used[v[j+1]]=true;
		if (v.size()%2) ans.pb(mp(v.back(), 2*i)), used[v.back()]=used[2*i]=true;
	}
	cout << ans.size() << endl;
	for (int i=0; i<ans.size(); i++) cout << ans[i].first << ' ' << ans[i].second << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int mod=int(1e9)+7;

typedef pair<int,int> PII;

long long s;
int f[100100],g[100100],num[100100];
int n;
vector<PII > ans;

int main(){
	cin >> n;
	memset(f,-1,sizeof(f));
	f[1]=1;
	for (int i=2;i<=n;i++)
		if (f[i]==-1){
			f[i]=i;
			for (int j=i;j<=n;j+=i) f[j]=i;
		}
	ans.clear();
	memset(g,0,sizeof(g));

	for (int i=2;i<=n;i++)
		if (f[i]!=-1) num[f[i]]++;
			else g[i]=1;
	//for (int i=1;i<=n;i++) cout<<f[i]<<" ";cout<<endl;
	for (int i=n/2;i>=2;i--)
		if (f[i]==i){
			vector<int> tmp;
			tmp.clear();
			for (int j=i;j<=n;j+=i){
				if (g[j]==0) tmp.push_back(j);
			}
			if (tmp.size()%2==1){
				swap(tmp[1],tmp[tmp.size()-1]);
			}
			for (int j=0;j+1<tmp.size();j+=2){
				ans.push_back(make_pair(tmp[j],tmp[j+1]));
				g[tmp[j]]=g[tmp[j+1]]=1;
			}
		}

	cout << ans.size()<<endl;
	for (int i=0;i<ans.size();i++)
		cout<<ans[i].first<<" "<<ans[i].second<<endl;
	return 0;
}


#include <algorithm>
#include <bitset>
#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

const int Nmax = 100005;

bitset<Nmax> Used;

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
    #endif

    ios :: sync_with_stdio(false);

    int N;
    cin >> N;

    vector< pair<int, int> > Ans;

    vector<int> RemNumers;

    for (int i = 2; i <= N; i <<= 1)
        RemNumers.push_back(i);

    for (int i = 3; i <= N / 2; i++)
    {
        if (!Used[i] && (i & 1))
        {
            vector<int> Numbers;
            for (int j = i; j <= N; j += i)
            {
                if (!Used[j])
                {
                    Used[j] = 1;
                    Numbers.push_back(j);
                }
            }

            if ((Numbers.size() & 1) && Numbers.size() > 1)
            {
                RemNumers.push_back(Numbers[1]);
                Numbers.erase(Numbers.begin() + 1);
            }

            for (int j = 0; j + 1 < int(Numbers.size()); j += 2)
                Ans.push_back(make_pair(Numbers[j], Numbers[j + 1]));
        }
    }

    for (int i = 0; i + 1 < int(RemNumers.size()); i += 2)
        Ans.push_back(make_pair(RemNumers[i], RemNumers[i + 1]));

    cout << Ans.size() << '\n';
    for (const auto p: Ans)
        cout << p.first << ' ' << p.second << '\n';

}


/*
 * Bidhan Roy
 * University of Dhaka
 */

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

#define foreach(i,n) for(__typeof((n).begin())i =(n).begin();i!=(n).end();i++)
#define sgn(x,y) ((x)+eps<(y)?-1:((x)>eps+(y)?1:0))
#define rep(i,n) for(__typeof(n) i=0; i<(n); i++)
#define mem(x,val) memset((x),(val),sizeof(x));
#define rite(x) freopen(x,"w",stdout);
#define read(x) freopen(x,"r",stdin);
#define all(x) x.begin(),x.end()
#define sz(x) ((int)x.size())
#define sqr(x) ((x)*(x))
#define pb push_back
#define mp make_pair
#define clr clear()
#define inf (1<<30)
#define ins insert
#define xx first
#define yy second
#define eps 1e-9

typedef long long i64;
typedef unsigned long long ui64;
typedef string st;
typedef vector<int> vi;
typedef vector<st> vs;
typedef map<int,int> mii;
typedef map<st,int> msi;
typedef set<int> si;
typedef set<st> ss;
typedef pair<int,int> pii;
typedef vector<pii> vpii;

#define mx 200000

bool taken[mx];

vpii ans;

int main(){
    //read("in");
    ios_base::sync_with_stdio(0);
    int n;
    cin >> n;
    for( int i = 2; i <= n; i++ ) {
        if( taken[i] ) continue;
        vi vec;
        //cout << "i=" << i << endl;
        for( int j = i; j <= n; j += i ) {
            if( taken[j] ) continue;
            vec.pb( j );
            //cout << "j===" << j << endl;
        }
        if( sz(vec) % 2 ) vec.pop_back();
        for( int i = 0; i < sz(vec); i += 2 ){
            taken[ vec[i] ] = true;
            taken[ vec[i+1] ] = true;
            ans.pb( {vec[i],vec[i+1]} );
        }
    }

    cout << sz(ans) << endl;
    for( auto x : ans ) cout << x.xx << " " << x.yy << endl;
    return 0;
}


/*
 * Bidhan Roy
 * University of Dhaka
 */

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

#define foreach(i,n) for(__typeof((n).begin())i =(n).begin();i!=(n).end();i++)
#define sgn(x,y) ((x)+eps<(y)?-1:((x)>eps+(y)?1:0))
#define rep(i,n) for(__typeof(n) i=0; i<(n); i++)
#define mem(x,val) memset((x),(val),sizeof(x));
#define rite(x) freopen(x,"w",stdout);
#define read(x) freopen(x,"r",stdin);
#define all(x) x.begin(),x.end()
#define sz(x) ((int)x.size())
#define sqr(x) ((x)*(x))
#define pb push_back
#define mp make_pair
#define clr clear()
#define inf (1<<30)
#define ins insert
#define xx first
#define yy second
#define eps 1e-9

typedef long long i64;
typedef unsigned long long ui64;
typedef string st;
typedef vector<int> vi;
typedef vector<st> vs;
typedef map<int,int> mii;
typedef map<st,int> msi;
typedef set<int> si;
typedef set<st> ss;
typedef pair<int,int> pii;
typedef vector<pii> vpii;

#define mx 200000

bool taken[mx];
bool vis[mx];

vpii ans;

int main(){
    //read("in");
    ios_base::sync_with_stdio(0);
    int n;
    cin >> n;
    for( int i = 3; i <= n / 2; i += 2 ) {
        if( taken[i] ) continue;
        if( vis[i] ) continue;
        int cnt = 0;
        for( int j = i; j <= n; j += i ) cnt += ( ! taken[j] );
        vi vec;
        //cout << " i= " << i << " cnt= " << cnt << endl;
        for( int j = i; j <= n; j += i ) {
            vis[j] = 1;
            if( taken[j] ) continue;
            if( (cnt % 2) == 1 && j == i+i ) continue;
            vec.pb( j );
        }
        assert( sz(vec) % 2 == 0 );
        for( int i = 0; i < sz(vec); i += 2 ){
            taken[ vec[i] ] = true;
            taken[ vec[i+1] ] = true;
            ans.pb( {vec[i],vec[i+1]} );
        }
    }

    vi vec;
    for( int i = 2; i <= n; i+=2 ) if( ! taken[i] ) vec.pb( i );
    for( int i = 0; i+1 < sz(vec); i += 2 ) ans.pb( { vec[i] , vec[i+1] } );
    cout << sz(ans) << endl;
    for( auto x : ans ) cout << x.xx << " " << x.yy << endl;
    return 0;
}


/*
 * Bidhan Roy
 * University of Dhaka
 */

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

#define foreach(i,n) for(__typeof((n).begin())i =(n).begin();i!=(n).end();i++)
#define sgn(x,y) ((x)+eps<(y)?-1:((x)>eps+(y)?1:0))
#define rep(i,n) for(__typeof(n) i=0; i<(n); i++)
#define mem(x,val) memset((x),(val),sizeof(x));
#define rite(x) freopen(x,"w",stdout);
#define read(x) freopen(x,"r",stdin);
#define all(x) x.begin(),x.end()
#define sz(x) ((int)x.size())
#define sqr(x) ((x)*(x))
#define pb push_back
#define mp make_pair
#define clr clear()
#define inf (1<<30)
#define ins insert
#define xx first
#define yy second
#define eps 1e-9

typedef long long i64;
typedef unsigned long long ui64;
typedef string st;
typedef vector<int> vi;
typedef vector<st> vs;
typedef map<int,int> mii;
typedef map<st,int> msi;
typedef set<int> si;
typedef set<st> ss;
typedef pair<int,int> pii;
typedef vector<pii> vpii;

#define mx 200000

bool taken[mx];
bool vis[mx];

vpii ans;

int main(){
    //read("in");
    ios_base::sync_with_stdio(0);
    int n;
    cin >> n;
    for( int i = 3; i <= n; i += 2 ) {
        if( taken[i] ) continue;
        if( vis[i] ) continue;
        int cnt = ( n / i ) - ( (i-1) / i );
        vi vec;
        for( int j = i; j <= n; j += i ) {
            vis[j] = 1;
            if( taken[j] ) continue;
            if( cnt % 2 && j == i+i ) continue;
            vec.pb( j );
        }
        for( int i = 0; i < sz(vec); i += 2 ){
            taken[ vec[i] ] = true;
            taken[ vec[i+1] ] = true;
            ans.pb( {vec[i],vec[i+1]} );
        }
    }

    vi vec;
    for( int i = 2; i <= n; i+=2 ) if( ! taken[i] ) vec.pb( i );
    if( sz(vec) > 1 )
        for( int  i = 0; i < sz(vec); i += 2 ) ans.pb( { vec[i] , vec[i+1] } );
    cout << sz(ans) << endl;
    for( auto x : ans ) cout << x.xx << " " << x.yy << endl;
    return 0;
}


/*
 * Bidhan Roy
 * University of Dhaka
 */

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

#define foreach(i,n) for(__typeof((n).begin())i =(n).begin();i!=(n).end();i++)
#define sgn(x,y) ((x)+eps<(y)?-1:((x)>eps+(y)?1:0))
#define rep(i,n) for(__typeof(n) i=0; i<(n); i++)
#define mem(x,val) memset((x),(val),sizeof(x));
#define rite(x) freopen(x,"w",stdout);
#define read(x) freopen(x,"r",stdin);
#define all(x) x.begin(),x.end()
#define sz(x) ((int)x.size())
#define sqr(x) ((x)*(x))
#define pb push_back
#define mp make_pair
#define clr clear()
#define inf (1<<30)
#define ins insert
#define xx first
#define yy second
#define eps 1e-9

typedef long long i64;
typedef unsigned long long ui64;
typedef string st;
typedef vector<int> vi;
typedef vector<st> vs;
typedef map<int,int> mii;
typedef map<st,int> msi;
typedef set<int> si;
typedef set<st> ss;
typedef pair<int,int> pii;
typedef vector<pii> vpii;

#define mx 200000

bool taken[mx];
bool vis[mx];

vpii ans;

int main(){
    //read("in");
    ios_base::sync_with_stdio(0);
    int n;
    cin >> n;
    for( int i = 3; i <= n / 2; i += 2 ) {
        if( taken[i] ) continue;
        if( vis[i] ) continue;
        int cnt = ( n / i ) - ( (i-1) / i );
        vi vec;
        for( int j = i; j <= n; j += i ) {
            vis[j] = 1;
            if( taken[j] ) continue;
            if( cnt % 2 && j == i+i ) continue;
            vec.pb( j );
        }
        if( sz(vec) % 2 ) vec.pop_back();
        for( int i = 0; i < sz(vec); i += 2 ){
            taken[ vec[i] ] = true;
            taken[ vec[i+1] ] = true;
            ans.pb( {vec[i],vec[i+1]} );
        }
    }

    vi vec;
    for( int i = 2; i <= n; i+=2 ) if( ! taken[i] ) vec.pb( i );
    if( sz(vec) > 1 )
        for( int  i = 0; i < sz(vec); i += 2 ) ans.pb( { vec[i] , vec[i+1] } );
    cout << sz(ans) << endl;
    for( auto x : ans ) cout << x.xx << " " << x.yy << endl;
    return 0;
}


/*
 * Bidhan Roy
 * University of Dhaka
 */

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

#define foreach(i,n) for(__typeof((n).begin())i =(n).begin();i!=(n).end();i++)
#define sgn(x,y) ((x)+eps<(y)?-1:((x)>eps+(y)?1:0))
#define rep(i,n) for(__typeof(n) i=0; i<(n); i++)
#define mem(x,val) memset((x),(val),sizeof(x));
#define rite(x) freopen(x,"w",stdout);
#define read(x) freopen(x,"r",stdin);
#define all(x) x.begin(),x.end()
#define sz(x) ((int)x.size())
#define sqr(x) ((x)*(x))
#define pb push_back
#define mp make_pair
#define clr clear()
#define inf (1<<30)
#define ins insert
#define xx first
#define yy second
#define eps 1e-9

typedef long long i64;
typedef unsigned long long ui64;
typedef string st;
typedef vector<int> vi;
typedef vector<st> vs;
typedef map<int,int> mii;
typedef map<st,int> msi;
typedef set<int> si;
typedef set<st> ss;
typedef pair<int,int> pii;
typedef vector<pii> vpii;

#define mx 200000

bool taken[mx];
bool vis[mx];

vpii ans;

int main(){
    //read("in");
    ios_base::sync_with_stdio(0);
    int n;
    cin >> n;
    for( int i = 3; i <= n / 2; i += 2 ) {
        if( taken[i] ) continue;
        if( vis[i] ) continue;
        vi vec;
        for( int j = i; j <= n; j += i ) {
            vis[j] = 1;
            if( taken[j] ) continue;
            vec.pb( j );
        }
        if( sz(vec) % 2 ) vec.pop_back();
        for( int i = 0; i < sz(vec); i += 2 ){
            taken[ vec[i] ] = true;
            taken[ vec[i+1] ] = true;
            ans.pb( {vec[i],vec[i+1]} );
        }
    }

    vi vec;
    for( int i = 2; i <= n; i+=2 ) if( ! taken[i] ) vec.pb( i );

    if( sz(vec) > 1 )
        for( int  i = 0; i < sz(vec); i += 2 ) ans.pb( { vec[i] , vec[i+1] } );

    cout << sz(ans) << endl;
    for( auto x : ans ) cout << x.xx << " " << x.yy << endl;
    return 0;
}


/*
 * Bidhan Roy
 * University of Dhaka
 */

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

#define foreach(i,n) for(__typeof((n).begin())i =(n).begin();i!=(n).end();i++)
#define sgn(x,y) ((x)+eps<(y)?-1:((x)>eps+(y)?1:0))
#define rep(i,n) for(__typeof(n) i=0; i<(n); i++)
#define mem(x,val) memset((x),(val),sizeof(x));
#define rite(x) freopen(x,"w",stdout);
#define read(x) freopen(x,"r",stdin);
#define all(x) x.begin(),x.end()
#define sz(x) ((int)x.size())
#define sqr(x) ((x)*(x))
#define pb push_back
#define mp make_pair
#define clr clear()
#define inf (1<<30)
#define ins insert
#define xx first
#define yy second
#define eps 1e-9

typedef long long i64;
typedef unsigned long long ui64;
typedef string st;
typedef vector<int> vi;
typedef vector<st> vs;
typedef map<int,int> mii;
typedef map<st,int> msi;
typedef set<int> si;
typedef set<st> ss;
typedef pair<int,int> pii;
typedef vector<pii> vpii;

#define mx 200000

bool taken[mx];

vpii ans;

int main(){
    read("in");
    ios_base::sync_with_stdio(0);
    int n;
    cin >> n;
    for( int i = 2; i <= n; i++ ) {
        if( taken[i] ) continue;
        vi vec;
        //cout << "i=" << i << endl;
        for( int j = i; j <= n; j += i ) {
            if( taken[j] ) continue;
            vec.pb( j );
            //cout << "j===" << j << endl;
        }
        if( sz(vec) % 2 ) vec.pop_back();
        for( int i = 0; i < sz(vec); i += 2 ){
            taken[ vec[i] ] = true;
            taken[ vec[i+1] ] = true;
            ans.pb( {vec[i],vec[i+1]} );
        }
    }

    cout << sz(ans) << endl;
    for( auto x : ans ) cout << x.xx << " " << x.yy << endl;
    return 0;
}


/*
 * Bidhan Roy
 * University of Dhaka
 */

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

#define foreach(i,n) for(__typeof((n).begin())i =(n).begin();i!=(n).end();i++)
#define sgn(x,y) ((x)+eps<(y)?-1:((x)>eps+(y)?1:0))
#define rep(i,n) for(__typeof(n) i=0; i<(n); i++)
#define mem(x,val) memset((x),(val),sizeof(x));
#define rite(x) freopen(x,"w",stdout);
#define read(x) freopen(x,"r",stdin);
#define all(x) x.begin(),x.end()
#define sz(x) ((int)x.size())
#define sqr(x) ((x)*(x))
#define pb push_back
#define mp make_pair
#define clr clear()
#define inf (1<<30)
#define ins insert
#define xx first
#define yy second
#define eps 1e-9

typedef long long i64;
typedef unsigned long long ui64;
typedef string st;
typedef vector<int> vi;
typedef vector<st> vs;
typedef map<int,int> mii;
typedef map<st,int> msi;
typedef set<int> si;
typedef set<st> ss;
typedef pair<int,int> pii;
typedef vector<pii> vpii;

#define mx 200000

bool taken[mx];
bool vis[mx];

vpii ans;

int main(){
    //read("in");
    ios_base::sync_with_stdio(0);
    int n;
    cin >> n;
    for( int i = 3; i <= n / 2; i += 2 ) {
        if( taken[i] ) continue;
        if( vis[i] ) continue;
        int cnt = 0;
        for( int j = i; j <= n; j += i ) cnt += ( ! taken[j] );
        vi vec;
        //cout << " i= " << i << " cnt= " << cnt << endl;
        for( int j = i; j <= n; j += i ) {
            vis[j] = 1;
            if( taken[j] ) continue;
            if( cnt % 2 && j == i+i ) continue;
            vec.pb( j );
        }
        for( int i = 0; i < sz(vec); i += 2 ){
            taken[ vec[i] ] = true;
            taken[ vec[i+1] ] = true;
            ans.pb( {vec[i],vec[i+1]} );
        }
    }

    vi vec;
    for( int i = 2; i <= n; i+=2 ) if( ! taken[i] ) vec.pb( i );
    if( sz(vec) > 1 )
        for( int  i = 0; i < sz(vec); i += 2 ) ans.pb( { vec[i] , vec[i+1] } );
    cout << sz(ans) << endl;
    for( auto x : ans ) cout << x.xx << " " << x.yy << endl;
    return 0;
}


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <sstream>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <stack>
#include <vector>

using namespace std;

#define pb push_back
#define mp make_pair
#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define foreach(e, x) for (__typeof(x.begin()) e = x.begin(); e != x.end(); e++)
typedef long long LL;
typedef pair<int, int> PII;

int n;
bool used[100001] = {};
vector<PII> ans;
bool p[100001];

int main() {
    cin >> n;
    REP(i, n + 1) p[i] = true;
    for (int i = 2; i * i <= n; ++i) if (p[i])
        for (int j = i * i; j <= n; j += i)
            p[j] = false;
    for (int i = 3; i <= (n >> 1); ++i) if (p[i]) {
        int prev = -1;
        for (int j = i; j <= n; j += i) if (j != (i << 1) && !used[j]) {
            if (prev == -1) prev = j;
            else {
                used[prev] = true;
                used[j] = true;
                ans.pb(mp(prev, j));
                prev = -1;
            }
        }
        if (prev != -1) {
            used[prev] = true;
            used[i << 1] = true;
            ans.pb(mp(prev, i << 1));
        }
    }
    int prev = -1;
    for (int i = 2; i <= n; i += 2) if (!used[i]) {
        if (prev == -1) prev = i;
        else {
            used[prev] = true;
            used[i] = true;
            ans.pb(mp(prev, i));
            prev = -1;
        }
    }
    printf("%d\n", (int)ans.size());
    REP(i, ans.size()) printf("%d %d\n", ans[i].first, ans[i].second);
    return 0;
}


#pragma comment(linker, "/stack:20000000")
#define _CRT_SECURE_NO_WARNINGS

# include <iostream>
# include <cmath>
# include <algorithm>
# include <cstdio>
# include <cstring>
# include <string>
# include <cstdlib>
# include <vector>
# include <bitset>
# include <map>
# include <queue>
# include <ctime>
# include <stack>
# include <set>
# include <list>
# include <deque>
# include <functional>
# include <sstream>
# include <fstream>
# include <complex>
# include <numeric>
using namespace std;

// Let's define unordered map
# ifdef __GNUC__
# if __cplusplus > 199711L
# include <unordered_map>
# else
# include <tr1/unordered_map>
using namespace std::tr1;
# endif
# else
# include <unordered_map>
# endif

#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL_((0,__VA_ARGS__, 5,4,3,2,1))
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NUM_ARGS_IMPL(_0,_1,_2,_3,_4,_5,N,...) N

#define macro_dispatcher(macro, ...) macro_dispatcher_(macro, VA_NUM_ARGS(__VA_ARGS__))
#define macro_dispatcher_(macro, nargs) macro_dispatcher__(macro, nargs)
#define macro_dispatcher__(macro, nargs) macro_dispatcher___(macro, nargs)
#define macro_dispatcher___(macro, nargs) macro ## nargs

#define DBN1(a)         std::cerr<<#a<<"="<<(a)<<"\n"
#define DBN2(a,b)       std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBN3(a,b,c)     std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"
#define DBN4(a,b,c,d)   std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<"\n"
#define DBN5(a,b,c,d,e) std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<"\n"

#define DEB(x) std::cerr<<#x<<"="<<(x)<<"  "

#ifdef DEBUG
#define DB(x) DEB(x)
#define DBN(...) macro_dispatcher(DBN, __VA_ARGS__)(__VA_ARGS__)
#define DA(a,n) cout<<#a<<"=["; printarray(a,n); cout<<"]\n"
#define DAR(a,n,s) cout<<#a<<"["<<s<<"-"<<n-1<<"]=["; printarray(a,n,s); cout<<"]\n"
#else
#define DB(x) ((void)42)
#define DBN(...) ((void)42)
#define DA(a,n) ((void)42)
#define DAR(a,n,s) ((void)42)
#endif

double __begin;
#define DTIME(ccc) __begin = clock(); ccc; std::cerr<<"Time of work = "<<(clock()-__begin)/CLOCKS_PER_SEC<<std::endl;

#define mp make_pair
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<long long,long long> pll;
typedef vector<int> vi;
typedef vector<long long> vll;

template<typename T1,typename T2,typename T3>
struct triple{T1 a;T2 b;T3 c;triple(){};triple(T1 _a,T2 _b, T3 _c):a(_a),b(_b),c(_c){}};
#define tri triple<int,int,int>
#define trl triple<ll,ll,ll>
template<typename T1,typename T2,typename T3>
bool operator<(const triple<T1,T2,T3> &t1,const triple<T1,T2,T3> &t2){if (t1.a!=t2.a) return t1.a<t2.a; else return t1.b<t2.b;}
template<typename T1, typename T2, typename T3>
inline std::ostream& operator << (std::ostream& os, const triple<T1, T2, T3>& t){ return os << "(" << t.a << ", " << t.b << ", " << t.c << ")"; }

#define FI(n) for(int i=0;i<n;i++)
#define FI1(n) for(int i=1;i<n;i++)
#define FJ(n) for(int j=0;j<n;j++)
#define FJ1(n) for(int j=1;j<n;j++)
#define FJI for(int j=0;j<i;j++)
#define FJI1 for(int j=1;j<i;j++)
#define FJIE for(int j=0;j<=i;j++)
#define FJIE1 for(int j=1;j<=i;j++)
#define For(i,a,b) for(int i=a;i<b;i++)

// Input macros
#define S(n)                        scanf("%d",&n)
#define S2(a,b)                     scanf("%d%d",&a,&b)
#define Sc(n)                       scanf("%c",&n)
#define Sl(n)                       scanf("%I64d",&n)
#define Sl2(a,b)                    scanf("%I64d%I63d",&a,&b)
#define Sf(n)                       scanf("%lf",&n)
#define Sf2(a,b)                    scanf("%lf%lf",&a,&b)

//Output macros
#define Pr(n)                       printf("%d ",n)
#define Prn(n)                      printf("%d\n",n)
#define Prc(n)                      printf("%c",n)
#define Prcn(n)                     printf("%c\n",n)
#define Prl(n)                      printf("%I64d ",n)
#define Prln(n)                     printf("%I64d\n",n)
#define Prf(n)                      printf("%lf ",n)
#define Prfn(n)                     printf("%lf\n",n)
#define Prs(n)                      printf("%s ",n)
#define Prsn(n)                     printf("%s\n",n)

//STL containers
#define foreach(v, c)               for( auto v = (c).begin();  v != (c).end(); ++v)
#define all(a)                      a.begin(), a.end()
#define in(a,b)                     ((b).find(a) != (b).end())
#define in2(a,b)                    (find(all(b),a) != (b).end())
#define pb                          push_back
#define sz(a)                       ((int)(a.size()))
#define svi(vec,n) FI(n) S(vec[y])
#define svl(vec,n) FI(n) Sl(vec[y])
#define IT ::iterator

//int some_primes[10] = {100271, 500179, 1000003, 2000227, 5000321}
//fill char arrays
#define fill(a,v)                    memset(a, v, sizeof (a))

inline int bits_count(int v){v=v-((v>>1)&0x55555555);v=(v&0x33333333)+((v>>2)&0x33333333);return((v+(v>>4)&0xF0F0F0F)*0x1010101)>>24;}
inline int bits_count(ll v){ int t = v >> 32; int p = (v & ((1LL << 32) - 1)); return bits_count(t) + bits_count(p); }
unsigned int reverse_bits(register unsigned int x){x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));return((x >> 16) | (x << 16));}
inline int sign(int x){return (x >> 31) | (-x >> 31);}
inline bool ispow2(int x){return (x!=0 && (x&(x-1))==0);}
#define checkbit(n,b)        ( (n >> b) & 1)
#define INDEX(arr,ind)       (lower_bound(all(arr),ind)-arr.begin())
#define sor(a)  sort(all(a))
#define rsor(a) sort(all(a)); reverse(all(a));

//STL output ********************************
template<typename T1,typename T2>inline std::ostream& operator << (std::ostream& os, const std::pair<T1, T2>& p){return os << "(" << p.first << ", " << p.second << ")";}
template<typename T>inline std::ostream &operator<<(std::ostream &os,const std::vector<T>& v){bool first=true;os<<"[";for(unsigned int i=0;i<v.size();i++){if(!first)os<<", ";os<<v[i];first=false;}return os<<"]";}
template<typename T1, typename T2>inline std::ostream &operator<<(std::ostream &os,const std::set<T1,T2>&v){bool first=true;os << "[";for(typename std::set<T1,T2>::const_iterator ii=v.begin();ii!=v.end();++ii){if(!first)os<<", ";os<<*ii;first=false;}return os<<"]";}
template<typename T1, typename T2>inline std::ostream &operator << (std::ostream & os,const std::map<T1, T2>& v){bool first = true; os << "[";for (typename std::map<T1,T2>::const_iterator ii =v.begin();ii!=v.end();++ii){if(!first)os<<", ";os<<*ii;first=false;}return os<<"]";}
template<typename T,typename T2>void printarray(T  a[],T2 sz,T2 beg=0){for(T2 i=beg;i<sz;i++) cout<<a[i]<<" ";cout<<endl;}

#define FREIN(FILE) freopen(FILE,"rt",stdin)
#define FREOUT(FILE) freopen(FILE,"wt",stdout)

#define sqr(x) ((x)*(x))
#define sqrt(x) sqrt(1.0*(x))
#define pow(x,n) pow(1.0*(x),n)

inline ll binpow(ll x,ll n){ll res=1;while(n){if(n&1)res*=x;x*=x;n>>=1;}return res;}
inline ll powmod(ll x,ll n, ll _mod){ll res=1;while(n){if(n&1)res=(res*x)%_mod;x=(x*x)%_mod;n>>=1;}return res;}
inline ll gcd(ll a,ll b){ll t;while(b){a=a%b;t=a;a=b;b=t;}return a;}
inline int gcd(int a,int b){int t;while(b){a=a%b;t=a;a=b;b=t;}return a;}
inline ll lcm(int a,int b){return a/gcd(a,b)*(ll)b;}
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
inline ll gcd(ll a,ll b,ll c){return gcd(gcd(a,b),c);}
inline int gcd(int a,int b,int c){return gcd(gcd(a,b),c);}
inline ll lcm(ll a,ll b,ll c){return lcm(lcm(a,b),c);}
inline ll lcm(int a,int b,int c){return lcm(lcm(a,b),(ll)c);}

inline ll max(ll a,ll b){return (a>b)?a:b;}
inline int max(int a,int b){return (a>b)?a:b;}
inline double max(double a,double b){return (a>b)?a:b;}
inline ll max(ll a,ll b,ll c){return max(a,max(b,c));}
inline int max(int a,int b,int c){return max(a,max(b,c));}
inline double max(double a,double b,double c){return max(a,max(b,c));}
inline ll min(ll a,ll b){return (a<b)?a:b;}
inline int min(int a,int b){return (a<b)?a:b;}
inline double min(double a,double b){return (a<b)?a:b;}
inline ll min(ll a,ll b,ll c){return min(a,min(b,c));}
inline int min(int a,int b,int c){return min(a,min(b,c));}
inline double min(double a,double b,double c){return min(a,min(b,c));}

template<class T>
inline void getar(T a, int n, int m){ for (int i = 0; i < n; i++) for (int j = 0; j < m;++j) { scanf("%d", &a[i][j]); } }
inline void getar(int *a, int n){ for (int ii = 0; ii < n; ii++){ scanf("%d", a + ii); } }
inline void getar(pii *a, int n){ for (int ii = 0; ii < n; ii++){ scanf("%d%d", &a[ii].first, &a[ii].second); } }
inline void getar(ll *a, int n){ for (int ii = 0; ii < n; ii++){ scanf("%I64d", a + ii); } }

// Useful constants

#define INF         1011111111
#define EPS         (double)1e-8
#define mod         1000000007
#define PI          3.14159265358979
//*******************************************************************************/

int pr[100010];
vector<int> primes;
vector<int> d[100001];
vector<int> v[100001];
int t[100001];
bool used[100001];
int z[100001];
struct Comp
{
    bool operator()(const int&x, const int&y)
    {
        return t[x] < t[y];
    }
};
set<int, Comp> s;
vector<pii> ans;
bool cmp(const int &x, const int& y)
{
    return z[x] > z[y];
}
int main()
{
    int n;
    cin >> n;
    for (int i = 2; i <= n; ++i)
    {
        if (pr[i] == 0)
        {
            pr[i] = i;
            primes.push_back(i);
        }
        for (int x : primes)
        {
            if (x * i > n) break;
            if (pr[i] < x) break;
            pr[x * i] = x;
        }
    }
    for (int i = n; i >= 2; --i)
    {
        int x = i;
        while (x != 1){
            int p = pr[x];
            d[i].push_back(p);
            while (pr[x] == p)
            {
                x /= p;
            }
            z[i] += n / p - 1;
            v[p].push_back(i);
        }
    }
    for (int i = 2; i <= n; ++i)
    {
        if (v[i].size() > 1)
        {
            sort(all(v[i]), cmp);
            //DBN(i, v[i]);
            t[i] = v[i].size();
            s.insert(i);
        }
    }
    while (!s.empty())
    {
        int p = *s.begin();
        s.erase(s.begin());

        int x = 0;
        int y = 0;
        for (int i = v[p].size() - 1; i >= 0; --i)
        {
            if (y) break;
            int val = v[p][i];
            if (!used[val])
            {
                if (!x) x = val;
                else y = val;
            }
            v[p].pop_back();
        }
        ans.push_back({ x, y });
        for (int p : d[x])
        {
            t[p]--;
        }
        for (int p : d[y])
        {
            t[p]--;
        }
        if (t[p] > 1)
            s.insert(p);
    }
    cout << ans.size() << '\n';
    for (pii p : ans)
    {
        cout << p.first << ' ' << p.second << '\n';
    }
    return 0;
}


#pragma comment(linker, "/stack:20000000")
#define _CRT_SECURE_NO_WARNINGS

# include <iostream>
# include <cmath>
# include <algorithm>
# include <cstdio>
# include <cstring>
# include <string>
# include <cstdlib>
# include <vector>
# include <bitset>
# include <map>
# include <queue>
# include <ctime>
# include <stack>
# include <set>
# include <list>
# include <deque>
# include <functional>
# include <sstream>
# include <fstream>
# include <complex>
# include <numeric>
using namespace std;

// Let's define unordered map
# ifdef __GNUC__
# if __cplusplus > 199711L
# include <unordered_map>
# else
# include <tr1/unordered_map>
using namespace std::tr1;
# endif
# else
# include <unordered_map>
# endif

#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL_((0,__VA_ARGS__, 5,4,3,2,1))
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NUM_ARGS_IMPL(_0,_1,_2,_3,_4,_5,N,...) N

#define macro_dispatcher(macro, ...) macro_dispatcher_(macro, VA_NUM_ARGS(__VA_ARGS__))
#define macro_dispatcher_(macro, nargs) macro_dispatcher__(macro, nargs)
#define macro_dispatcher__(macro, nargs) macro_dispatcher___(macro, nargs)
#define macro_dispatcher___(macro, nargs) macro ## nargs

#define DBN1(a)         std::cerr<<#a<<"="<<(a)<<"\n"
#define DBN2(a,b)       std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBN3(a,b,c)     std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"
#define DBN4(a,b,c,d)   std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<"\n"
#define DBN5(a,b,c,d,e) std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<"\n"

#define DEB(x) std::cerr<<#x<<"="<<(x)<<"  "

#ifdef DEBUG
#define DB(x) DEB(x)
#define DBN(...) macro_dispatcher(DBN, __VA_ARGS__)(__VA_ARGS__)
#define DA(a,n) cout<<#a<<"=["; printarray(a,n); cout<<"]\n"
#define DAR(a,n,s) cout<<#a<<"["<<s<<"-"<<n-1<<"]=["; printarray(a,n,s); cout<<"]\n"
#else
#define DB(x) ((void)42)
#define DBN(...) ((void)42)
#define DA(a,n) ((void)42)
#define DAR(a,n,s) ((void)42)
#endif

double __begin;
#define DTIME(ccc) __begin = clock(); ccc; std::cerr<<"Time of work = "<<(clock()-__begin)/CLOCKS_PER_SEC<<std::endl;

#define mp make_pair
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<long long,long long> pll;
typedef vector<int> vi;
typedef vector<long long> vll;

template<typename T1,typename T2,typename T3>
struct triple{T1 a;T2 b;T3 c;triple(){};triple(T1 _a,T2 _b, T3 _c):a(_a),b(_b),c(_c){}};
#define tri triple<int,int,int>
#define trl triple<ll,ll,ll>
template<typename T1,typename T2,typename T3>
bool operator<(const triple<T1,T2,T3> &t1,const triple<T1,T2,T3> &t2){if (t1.a!=t2.a) return t1.a<t2.a; else return t1.b<t2.b;}
template<typename T1, typename T2, typename T3>
inline std::ostream& operator << (std::ostream& os, const triple<T1, T2, T3>& t){ return os << "(" << t.a << ", " << t.b << ", " << t.c << ")"; }

#define FI(n) for(int i=0;i<n;i++)
#define FI1(n) for(int i=1;i<n;i++)
#define FJ(n) for(int j=0;j<n;j++)
#define FJ1(n) for(int j=1;j<n;j++)
#define FJI for(int j=0;j<i;j++)
#define FJI1 for(int j=1;j<i;j++)
#define FJIE for(int j=0;j<=i;j++)
#define FJIE1 for(int j=1;j<=i;j++)
#define For(i,a,b) for(int i=a;i<b;i++)

// Input macros
#define S(n)                        scanf("%d",&n)
#define S2(a,b)                     scanf("%d%d",&a,&b)
#define Sc(n)                       scanf("%c",&n)
#define Sl(n)                       scanf("%I64d",&n)
#define Sl2(a,b)                    scanf("%I64d%I63d",&a,&b)
#define Sf(n)                       scanf("%lf",&n)
#define Sf2(a,b)                    scanf("%lf%lf",&a,&b)

//Output macros
#define Pr(n)                       printf("%d ",n)
#define Prn(n)                      printf("%d\n",n)
#define Prc(n)                      printf("%c",n)
#define Prcn(n)                     printf("%c\n",n)
#define Prl(n)                      printf("%I64d ",n)
#define Prln(n)                     printf("%I64d\n",n)
#define Prf(n)                      printf("%lf ",n)
#define Prfn(n)                     printf("%lf\n",n)
#define Prs(n)                      printf("%s ",n)
#define Prsn(n)                     printf("%s\n",n)

//STL containers
#define foreach(v, c)               for( auto v = (c).begin();  v != (c).end(); ++v)
#define all(a)                      a.begin(), a.end()
#define in(a,b)                     ((b).find(a) != (b).end())
#define in2(a,b)                    (find(all(b),a) != (b).end())
#define pb                          push_back
#define sz(a)                       ((int)(a.size()))
#define svi(vec,n) FI(n) S(vec[y])
#define svl(vec,n) FI(n) Sl(vec[y])
#define IT ::iterator

//int some_primes[10] = {100271, 500179, 1000003, 2000227, 5000321}
//fill char arrays
#define fill(a,v)                    memset(a, v, sizeof (a))

inline int bits_count(int v){v=v-((v>>1)&0x55555555);v=(v&0x33333333)+((v>>2)&0x33333333);return((v+(v>>4)&0xF0F0F0F)*0x1010101)>>24;}
inline int bits_count(ll v){ int t = v >> 32; int p = (v & ((1LL << 32) - 1)); return bits_count(t) + bits_count(p); }
unsigned int reverse_bits(register unsigned int x){x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));return((x >> 16) | (x << 16));}
inline int sign(int x){return (x >> 31) | (-x >> 31);}
inline bool ispow2(int x){return (x!=0 && (x&(x-1))==0);}
#define checkbit(n,b)        ( (n >> b) & 1)
#define INDEX(arr,ind)       (lower_bound(all(arr),ind)-arr.begin())
#define sor(a)  sort(all(a))
#define rsor(a) sort(all(a)); reverse(all(a));

//STL output ********************************
template<typename T1,typename T2>inline std::ostream& operator << (std::ostream& os, const std::pair<T1, T2>& p){return os << "(" << p.first << ", " << p.second << ")";}
template<typename T>inline std::ostream &operator<<(std::ostream &os,const std::vector<T>& v){bool first=true;os<<"[";for(unsigned int i=0;i<v.size();i++){if(!first)os<<", ";os<<v[i];first=false;}return os<<"]";}
template<typename T1, typename T2>inline std::ostream &operator<<(std::ostream &os,const std::set<T1,T2>&v){bool first=true;os << "[";for(typename std::set<T1,T2>::const_iterator ii=v.begin();ii!=v.end();++ii){if(!first)os<<", ";os<<*ii;first=false;}return os<<"]";}
template<typename T1, typename T2>inline std::ostream &operator << (std::ostream & os,const std::map<T1, T2>& v){bool first = true; os << "[";for (typename std::map<T1,T2>::const_iterator ii =v.begin();ii!=v.end();++ii){if(!first)os<<", ";os<<*ii;first=false;}return os<<"]";}
template<typename T,typename T2>void printarray(T  a[],T2 sz,T2 beg=0){for(T2 i=beg;i<sz;i++) cout<<a[i]<<" ";cout<<endl;}

#define FREIN(FILE) freopen(FILE,"rt",stdin)
#define FREOUT(FILE) freopen(FILE,"wt",stdout)

#define sqr(x) ((x)*(x))
#define sqrt(x) sqrt(1.0*(x))
#define pow(x,n) pow(1.0*(x),n)

inline ll binpow(ll x,ll n){ll res=1;while(n){if(n&1)res*=x;x*=x;n>>=1;}return res;}
inline ll powmod(ll x,ll n, ll _mod){ll res=1;while(n){if(n&1)res=(res*x)%_mod;x=(x*x)%_mod;n>>=1;}return res;}
inline ll gcd(ll a,ll b){ll t;while(b){a=a%b;t=a;a=b;b=t;}return a;}
inline int gcd(int a,int b){int t;while(b){a=a%b;t=a;a=b;b=t;}return a;}
inline ll lcm(int a,int b){return a/gcd(a,b)*(ll)b;}
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
inline ll gcd(ll a,ll b,ll c){return gcd(gcd(a,b),c);}
inline int gcd(int a,int b,int c){return gcd(gcd(a,b),c);}
inline ll lcm(ll a,ll b,ll c){return lcm(lcm(a,b),c);}
inline ll lcm(int a,int b,int c){return lcm(lcm(a,b),(ll)c);}

inline ll max(ll a,ll b){return (a>b)?a:b;}
inline int max(int a,int b){return (a>b)?a:b;}
inline double max(double a,double b){return (a>b)?a:b;}
inline ll max(ll a,ll b,ll c){return max(a,max(b,c));}
inline int max(int a,int b,int c){return max(a,max(b,c));}
inline double max(double a,double b,double c){return max(a,max(b,c));}
inline ll min(ll a,ll b){return (a<b)?a:b;}
inline int min(int a,int b){return (a<b)?a:b;}
inline double min(double a,double b){return (a<b)?a:b;}
inline ll min(ll a,ll b,ll c){return min(a,min(b,c));}
inline int min(int a,int b,int c){return min(a,min(b,c));}
inline double min(double a,double b,double c){return min(a,min(b,c));}

template<class T>
inline void getar(T a, int n, int m){ for (int i = 0; i < n; i++) for (int j = 0; j < m;++j) { scanf("%d", &a[i][j]); } }
inline void getar(int *a, int n){ for (int ii = 0; ii < n; ii++){ scanf("%d", a + ii); } }
inline void getar(pii *a, int n){ for (int ii = 0; ii < n; ii++){ scanf("%d%d", &a[ii].first, &a[ii].second); } }
inline void getar(ll *a, int n){ for (int ii = 0; ii < n; ii++){ scanf("%I64d", a + ii); } }

// Useful constants

#define INF         1011111111
#define EPS         (double)1e-8
#define mod         1000000007
#define PI          3.14159265358979
//*******************************************************************************/

int pr[100010];
vector<int> primes;
vector<int> d[100001];
vector<int> v[100001];
int t[100001];
bool used[100001];
int z[100001];
struct Comp
{
    bool operator()(const int&x, const int&y)
    {
        return t[x] < t[y];
    }
};
set<int, Comp> s;
vector<pii> ans;
bool cmp(const int &x, const int& y)
{
    return z[x] > z[y];
}
int main()
{
    int n;
    cin >> n;
    for (int i = 2; i <= n; ++i)
    {
        if (pr[i] == 0)
        {
            pr[i] = i;
            primes.push_back(i);
        }
        for (int x : primes)
        {
            if (x * i > n) break;
            if (pr[i] < x) break;
            pr[x * i] = x;
        }
    }
    for (int i = n; i >= 2; --i)
    {
        int x = i;
        while (x != 1){
            int p = pr[x];
            d[i].push_back(p);
            while (pr[x] == p)
            {
                x /= p;
            }
            z[i] += n / p + (rand()%(n/3));
            v[p].push_back(i);
        }
    }
    for (int i = 2; i <= n; ++i)
    {
        if (v[i].size() > 1)
        {
            sort(all(v[i]), cmp);
            //DBN(i, v[i]);
            t[i] = v[i].size();
            s.insert(i);
        }
    }
    while (!s.empty())
    {
        int p = *s.begin();
        s.erase(s.begin());

        int x = 0;
        int y = 0;
        for (int i = v[p].size() - 1; i >= 0; --i)
        {
            if (y) break;
            int val = v[p][i];
            if (!used[val])
            {
                if (!x) x = val;
                else y = val;
            }
            v[p].pop_back();
        }
        ans.push_back({ x, y });
        for (int p : d[x])
        {
            t[p]--;
        }
        for (int p : d[y])
        {
            t[p]--;
        }
        if (t[p] > 1)
            s.insert(p);
    }
    cout << ans.size() << '\n';
    for (pii p : ans)
    {
        cout << p.first << ' ' << p.second << '\n';
    }
    return 0;
}


#pragma comment(linker, "/stack:20000000")
#define _CRT_SECURE_NO_WARNINGS

# include <iostream>
# include <cmath>
# include <algorithm>
# include <cstdio>
# include <cstring>
# include <string>
# include <cstdlib>
# include <vector>
# include <bitset>
# include <map>
# include <queue>
# include <ctime>
# include <stack>
# include <set>
# include <list>
# include <deque>
# include <functional>
# include <sstream>
# include <fstream>
# include <complex>
# include <numeric>
using namespace std;

// Let's define unordered map
# ifdef __GNUC__
# if __cplusplus > 199711L
# include <unordered_map>
# else
# include <tr1/unordered_map>
using namespace std::tr1;
# endif
# else
# include <unordered_map>
# endif

#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL_((0,__VA_ARGS__, 5,4,3,2,1))
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NUM_ARGS_IMPL(_0,_1,_2,_3,_4,_5,N,...) N

#define macro_dispatcher(macro, ...) macro_dispatcher_(macro, VA_NUM_ARGS(__VA_ARGS__))
#define macro_dispatcher_(macro, nargs) macro_dispatcher__(macro, nargs)
#define macro_dispatcher__(macro, nargs) macro_dispatcher___(macro, nargs)
#define macro_dispatcher___(macro, nargs) macro ## nargs

#define DBN1(a)         std::cerr<<#a<<"="<<(a)<<"\n"
#define DBN2(a,b)       std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBN3(a,b,c)     std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"
#define DBN4(a,b,c,d)   std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<"\n"
#define DBN5(a,b,c,d,e) std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<"\n"

#define DEB(x) std::cerr<<#x<<"="<<(x)<<"  "

#ifdef DEBUG
#define DB(x) DEB(x)
#define DBN(...) macro_dispatcher(DBN, __VA_ARGS__)(__VA_ARGS__)
#define DA(a,n) cout<<#a<<"=["; printarray(a,n); cout<<"]\n"
#define DAR(a,n,s) cout<<#a<<"["<<s<<"-"<<n-1<<"]=["; printarray(a,n,s); cout<<"]\n"
#else
#define DB(x) ((void)42)
#define DBN(...) ((void)42)
#define DA(a,n) ((void)42)
#define DAR(a,n,s) ((void)42)
#endif

double __begin;
#define DTIME(ccc) __begin = clock(); ccc; std::cerr<<"Time of work = "<<(clock()-__begin)/CLOCKS_PER_SEC<<std::endl;

#define mp make_pair
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<long long,long long> pll;
typedef vector<int> vi;
typedef vector<long long> vll;

template<typename T1,typename T2,typename T3>
struct triple{T1 a;T2 b;T3 c;triple(){};triple(T1 _a,T2 _b, T3 _c):a(_a),b(_b),c(_c){}};
#define tri triple<int,int,int>
#define trl triple<ll,ll,ll>
template<typename T1,typename T2,typename T3>
bool operator<(const triple<T1,T2,T3> &t1,const triple<T1,T2,T3> &t2){if (t1.a!=t2.a) return t1.a<t2.a; else return t1.b<t2.b;}
template<typename T1, typename T2, typename T3>
inline std::ostream& operator << (std::ostream& os, const triple<T1, T2, T3>& t){ return os << "(" << t.a << ", " << t.b << ", " << t.c << ")"; }

#define FI(n) for(int i=0;i<n;i++)
#define FI1(n) for(int i=1;i<n;i++)
#define FJ(n) for(int j=0;j<n;j++)
#define FJ1(n) for(int j=1;j<n;j++)
#define FJI for(int j=0;j<i;j++)
#define FJI1 for(int j=1;j<i;j++)
#define FJIE for(int j=0;j<=i;j++)
#define FJIE1 for(int j=1;j<=i;j++)
#define For(i,a,b) for(int i=a;i<b;i++)

// Input macros
#define S(n)                        scanf("%d",&n)
#define S2(a,b)                     scanf("%d%d",&a,&b)
#define Sc(n)                       scanf("%c",&n)
#define Sl(n)                       scanf("%I64d",&n)
#define Sl2(a,b)                    scanf("%I64d%I63d",&a,&b)
#define Sf(n)                       scanf("%lf",&n)
#define Sf2(a,b)                    scanf("%lf%lf",&a,&b)

//Output macros
#define Pr(n)                       printf("%d ",n)
#define Prn(n)                      printf("%d\n",n)
#define Prc(n)                      printf("%c",n)
#define Prcn(n)                     printf("%c\n",n)
#define Prl(n)                      printf("%I64d ",n)
#define Prln(n)                     printf("%I64d\n",n)
#define Prf(n)                      printf("%lf ",n)
#define Prfn(n)                     printf("%lf\n",n)
#define Prs(n)                      printf("%s ",n)
#define Prsn(n)                     printf("%s\n",n)

//STL containers
#define foreach(v, c)               for( auto v = (c).begin();  v != (c).end(); ++v)
#define all(a)                      a.begin(), a.end()
#define in(a,b)                     ((b).find(a) != (b).end())
#define in2(a,b)                    (find(all(b),a) != (b).end())
#define pb                          push_back
#define sz(a)                       ((int)(a.size()))
#define svi(vec,n) FI(n) S(vec[y])
#define svl(vec,n) FI(n) Sl(vec[y])
#define IT ::iterator

//int some_primes[10] = {100271, 500179, 1000003, 2000227, 5000321}
//fill char arrays
#define fill(a,v)                    memset(a, v, sizeof (a))

inline int bits_count(int v){v=v-((v>>1)&0x55555555);v=(v&0x33333333)+((v>>2)&0x33333333);return((v+(v>>4)&0xF0F0F0F)*0x1010101)>>24;}
inline int bits_count(ll v){ int t = v >> 32; int p = (v & ((1LL << 32) - 1)); return bits_count(t) + bits_count(p); }
unsigned int reverse_bits(register unsigned int x){x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));return((x >> 16) | (x << 16));}
inline int sign(int x){return (x >> 31) | (-x >> 31);}
inline bool ispow2(int x){return (x!=0 && (x&(x-1))==0);}
#define checkbit(n,b)        ( (n >> b) & 1)
#define INDEX(arr,ind)       (lower_bound(all(arr),ind)-arr.begin())
#define sor(a)  sort(all(a))
#define rsor(a) sort(all(a)); reverse(all(a));

//STL output ********************************
template<typename T1,typename T2>inline std::ostream& operator << (std::ostream& os, const std::pair<T1, T2>& p){return os << "(" << p.first << ", " << p.second << ")";}
template<typename T>inline std::ostream &operator<<(std::ostream &os,const std::vector<T>& v){bool first=true;os<<"[";for(unsigned int i=0;i<v.size();i++){if(!first)os<<", ";os<<v[i];first=false;}return os<<"]";}
template<typename T1, typename T2>inline std::ostream &operator<<(std::ostream &os,const std::set<T1,T2>&v){bool first=true;os << "[";for(typename std::set<T1,T2>::const_iterator ii=v.begin();ii!=v.end();++ii){if(!first)os<<", ";os<<*ii;first=false;}return os<<"]";}
template<typename T1, typename T2>inline std::ostream &operator << (std::ostream & os,const std::map<T1, T2>& v){bool first = true; os << "[";for (typename std::map<T1,T2>::const_iterator ii =v.begin();ii!=v.end();++ii){if(!first)os<<", ";os<<*ii;first=false;}return os<<"]";}
template<typename T,typename T2>void printarray(T  a[],T2 sz,T2 beg=0){for(T2 i=beg;i<sz;i++) cout<<a[i]<<" ";cout<<endl;}

#define FREIN(FILE) freopen(FILE,"rt",stdin)
#define FREOUT(FILE) freopen(FILE,"wt",stdout)

#define sqr(x) ((x)*(x))
#define sqrt(x) sqrt(1.0*(x))
#define pow(x,n) pow(1.0*(x),n)

inline ll binpow(ll x,ll n){ll res=1;while(n){if(n&1)res*=x;x*=x;n>>=1;}return res;}
inline ll powmod(ll x,ll n, ll _mod){ll res=1;while(n){if(n&1)res=(res*x)%_mod;x=(x*x)%_mod;n>>=1;}return res;}
inline ll gcd(ll a,ll b){ll t;while(b){a=a%b;t=a;a=b;b=t;}return a;}
inline int gcd(int a,int b){int t;while(b){a=a%b;t=a;a=b;b=t;}return a;}
inline ll lcm(int a,int b){return a/gcd(a,b)*(ll)b;}
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
inline ll gcd(ll a,ll b,ll c){return gcd(gcd(a,b),c);}
inline int gcd(int a,int b,int c){return gcd(gcd(a,b),c);}
inline ll lcm(ll a,ll b,ll c){return lcm(lcm(a,b),c);}
inline ll lcm(int a,int b,int c){return lcm(lcm(a,b),(ll)c);}

inline ll max(ll a,ll b){return (a>b)?a:b;}
inline int max(int a,int b){return (a>b)?a:b;}
inline double max(double a,double b){return (a>b)?a:b;}
inline ll max(ll a,ll b,ll c){return max(a,max(b,c));}
inline int max(int a,int b,int c){return max(a,max(b,c));}
inline double max(double a,double b,double c){return max(a,max(b,c));}
inline ll min(ll a,ll b){return (a<b)?a:b;}
inline int min(int a,int b){return (a<b)?a:b;}
inline double min(double a,double b){return (a<b)?a:b;}
inline ll min(ll a,ll b,ll c){return min(a,min(b,c));}
inline int min(int a,int b,int c){return min(a,min(b,c));}
inline double min(double a,double b,double c){return min(a,min(b,c));}

template<class T>
inline void getar(T a, int n, int m){ for (int i = 0; i < n; i++) for (int j = 0; j < m;++j) { scanf("%d", &a[i][j]); } }
inline void getar(int *a, int n){ for (int ii = 0; ii < n; ii++){ scanf("%d", a + ii); } }
inline void getar(pii *a, int n){ for (int ii = 0; ii < n; ii++){ scanf("%d%d", &a[ii].first, &a[ii].second); } }
inline void getar(ll *a, int n){ for (int ii = 0; ii < n; ii++){ scanf("%I64d", a + ii); } }

// Useful constants

#define INF         1011111111
#define EPS         (double)1e-8
#define mod         1000000007
#define PI          3.14159265358979
//*******************************************************************************/

vector<int> v[100010];
int pr[100010];
vi primes;
vector<int> odd;
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    for (int i = 2; i <= n; ++i)
    {
        if (pr[i] == 0)
        {
            pr[i] = i;
            primes.push_back(i);
        }
        for (int x : primes)
        {
            if (x * i > n) break;
            if (pr[i] < x) break;
            pr[x * i] = x;
        }
    }
    for (int i = 2; i <= n; ++i)
    {
        if ((i&(i - 1)) == 0)
        {
            odd.push_back(i);
            pr[i] = i;
        }
        else
        {
            int x = i;
            if (pr[x] == 2)
            {
                x >>= 1;
            }
            pr[i] = pr[x];
            v[pr[i]].push_back(i);
        }
    }
    vector<pii> ans;
    ans.reserve(n / 2);
    for (int i = 2; i <= n; ++i)
    {
        if (v[i].size() > 1)
        {
            if (v[i].size() & 1)
            {
                odd.push_back(v[i][1]);
                ans.push_back(pii(v[i][0], v[i][2]));
                for (int j = 3; j < v[i].size(); j += 2)
                {
                    ans.push_back(pii(v[i][j], v[i][j + 1]));
                }
            }
            else
            {
                for (int j = 0; j < v[i].size(); j += 2)
                {
                    ans.push_back(pii(v[i][j], v[i][j + 1]));
                }
            }
        }
    }
    for (int i = 1; i < odd.size(); i += 2)
    {
        ans.push_back(pii(odd[i], odd[i - 1]));
    }
    cout << ans.size() << '\n';
    for (int i = 0; i < ans.size(); ++i)
    {
        cout << ans[i].first << ' ' << ans[i].second << '\n';
    }
    return 0;
}


#pragma comment(linker, "/stack:20000000")
#define _CRT_SECURE_NO_WARNINGS

# include <iostream>
# include <cmath>
# include <algorithm>
# include <cstdio>
# include <cstring>
# include <string>
# include <cstdlib>
# include <vector>
# include <bitset>
# include <map>
# include <queue>
# include <ctime>
# include <stack>
# include <set>
# include <list>
# include <deque>
# include <functional>
# include <sstream>
# include <fstream>
# include <complex>
# include <numeric>
using namespace std;

// Let's define unordered map
# ifdef __GNUC__
# if __cplusplus > 199711L
# include <unordered_map>
# else
# include <tr1/unordered_map>
using namespace std::tr1;
# endif
# else
# include <unordered_map>
# endif

#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL_((0,__VA_ARGS__, 5,4,3,2,1))
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NUM_ARGS_IMPL(_0,_1,_2,_3,_4,_5,N,...) N

#define macro_dispatcher(macro, ...) macro_dispatcher_(macro, VA_NUM_ARGS(__VA_ARGS__))
#define macro_dispatcher_(macro, nargs) macro_dispatcher__(macro, nargs)
#define macro_dispatcher__(macro, nargs) macro_dispatcher___(macro, nargs)
#define macro_dispatcher___(macro, nargs) macro ## nargs

#define DBN1(a)         std::cerr<<#a<<"="<<(a)<<"\n"
#define DBN2(a,b)       std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBN3(a,b,c)     std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"
#define DBN4(a,b,c,d)   std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<"\n"
#define DBN5(a,b,c,d,e) std::cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<"\n"

#define DEB(x) std::cerr<<#x<<"="<<(x)<<"  "

#ifdef DEBUG
#define DB(x) DEB(x)
#define DBN(...) macro_dispatcher(DBN, __VA_ARGS__)(__VA_ARGS__)
#define DA(a,n) cout<<#a<<"=["; printarray(a,n); cout<<"]\n"
#define DAR(a,n,s) cout<<#a<<"["<<s<<"-"<<n-1<<"]=["; printarray(a,n,s); cout<<"]\n"
#else
#define DB(x) ((void)42)
#define DBN(...) ((void)42)
#define DA(a,n) ((void)42)
#define DAR(a,n,s) ((void)42)
#endif

double __begin;
#define DTIME(ccc) __begin = clock(); ccc; std::cerr<<"Time of work = "<<(clock()-__begin)/CLOCKS_PER_SEC<<std::endl;

#define mp make_pair
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<long long,long long> pll;
typedef vector<int> vi;
typedef vector<long long> vll;

template<typename T1,typename T2,typename T3>
struct triple{T1 a;T2 b;T3 c;triple(){};triple(T1 _a,T2 _b, T3 _c):a(_a),b(_b),c(_c){}};
#define tri triple<int,int,int>
#define trl triple<ll,ll,ll>
template<typename T1,typename T2,typename T3>
bool operator<(const triple<T1,T2,T3> &t1,const triple<T1,T2,T3> &t2){if (t1.a!=t2.a) return t1.a<t2.a; else return t1.b<t2.b;}
template<typename T1, typename T2, typename T3>
inline std::ostream& operator << (std::ostream& os, const triple<T1, T2, T3>& t){ return os << "(" << t.a << ", " << t.b << ", " << t.c << ")"; }

#define FI(n) for(int i=0;i<n;i++)
#define FI1(n) for(int i=1;i<n;i++)
#define FJ(n) for(int j=0;j<n;j++)
#define FJ1(n) for(int j=1;j<n;j++)
#define FJI for(int j=0;j<i;j++)
#define FJI1 for(int j=1;j<i;j++)
#define FJIE for(int j=0;j<=i;j++)
#define FJIE1 for(int j=1;j<=i;j++)
#define For(i,a,b) for(int i=a;i<b;i++)

// Input macros
#define S(n)                        scanf("%d",&n)
#define S2(a,b)                     scanf("%d%d",&a,&b)
#define Sc(n)                       scanf("%c",&n)
#define Sl(n)                       scanf("%I64d",&n)
#define Sl2(a,b)                    scanf("%I64d%I63d",&a,&b)
#define Sf(n)                       scanf("%lf",&n)
#define Sf2(a,b)                    scanf("%lf%lf",&a,&b)

//Output macros
#define Pr(n)                       printf("%d ",n)
#define Prn(n)                      printf("%d\n",n)
#define Prc(n)                      printf("%c",n)
#define Prcn(n)                     printf("%c\n",n)
#define Prl(n)                      printf("%I64d ",n)
#define Prln(n)                     printf("%I64d\n",n)
#define Prf(n)                      printf("%lf ",n)
#define Prfn(n)                     printf("%lf\n",n)
#define Prs(n)                      printf("%s ",n)
#define Prsn(n)                     printf("%s\n",n)

//STL containers
#define foreach(v, c)               for( auto v = (c).begin();  v != (c).end(); ++v)
#define all(a)                      a.begin(), a.end()
#define in(a,b)                     ((b).find(a) != (b).end())
#define in2(a,b)                    (find(all(b),a) != (b).end())
#define pb                          push_back
#define sz(a)                       ((int)(a.size()))
#define svi(vec,n) FI(n) S(vec[y])
#define svl(vec,n) FI(n) Sl(vec[y])
#define IT ::iterator

//int some_primes[10] = {100271, 500179, 1000003, 2000227, 5000321}
//fill char arrays
#define fill(a,v)                    memset(a, v, sizeof (a))

inline int bits_count(int v){v=v-((v>>1)&0x55555555);v=(v&0x33333333)+((v>>2)&0x33333333);return((v+(v>>4)&0xF0F0F0F)*0x1010101)>>24;}
inline int bits_count(ll v){ int t = v >> 32; int p = (v & ((1LL << 32) - 1)); return bits_count(t) + bits_count(p); }
unsigned int reverse_bits(register unsigned int x){x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));return((x >> 16) | (x << 16));}
inline int sign(int x){return (x >> 31) | (-x >> 31);}
inline bool ispow2(int x){return (x!=0 && (x&(x-1))==0);}
#define checkbit(n,b)        ( (n >> b) & 1)
#define INDEX(arr,ind)       (lower_bound(all(arr),ind)-arr.begin())
#define sor(a)  sort(all(a))
#define rsor(a) sort(all(a)); reverse(all(a));

//STL output ********************************
template<typename T1,typename T2>inline std::ostream& operator << (std::ostream& os, const std::pair<T1, T2>& p){return os << "(" << p.first << ", " << p.second << ")";}
template<typename T>inline std::ostream &operator<<(std::ostream &os,const std::vector<T>& v){bool first=true;os<<"[";for(unsigned int i=0;i<v.size();i++){if(!first)os<<", ";os<<v[i];first=false;}return os<<"]";}
template<typename T1, typename T2>inline std::ostream &operator<<(std::ostream &os,const std::set<T1,T2>&v){bool first=true;os << "[";for(typename std::set<T1,T2>::const_iterator ii=v.begin();ii!=v.end();++ii){if(!first)os<<", ";os<<*ii;first=false;}return os<<"]";}
template<typename T1, typename T2>inline std::ostream &operator << (std::ostream & os,const std::map<T1, T2>& v){bool first = true; os << "[";for (typename std::map<T1,T2>::const_iterator ii =v.begin();ii!=v.end();++ii){if(!first)os<<", ";os<<*ii;first=false;}return os<<"]";}
template<typename T,typename T2>void printarray(T  a[],T2 sz,T2 beg=0){for(T2 i=beg;i<sz;i++) cout<<a[i]<<" ";cout<<endl;}

#define FREIN(FILE) freopen(FILE,"rt",stdin)
#define FREOUT(FILE) freopen(FILE,"wt",stdout)

#define sqr(x) ((x)*(x))
#define sqrt(x) sqrt(1.0*(x))
#define pow(x,n) pow(1.0*(x),n)

inline ll binpow(ll x,ll n){ll res=1;while(n){if(n&1)res*=x;x*=x;n>>=1;}return res;}
inline ll powmod(ll x,ll n, ll _mod){ll res=1;while(n){if(n&1)res=(res*x)%_mod;x=(x*x)%_mod;n>>=1;}return res;}
inline ll gcd(ll a,ll b){ll t;while(b){a=a%b;t=a;a=b;b=t;}return a;}
inline int gcd(int a,int b){int t;while(b){a=a%b;t=a;a=b;b=t;}return a;}
inline ll lcm(int a,int b){return a/gcd(a,b)*(ll)b;}
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
inline ll gcd(ll a,ll b,ll c){return gcd(gcd(a,b),c);}
inline int gcd(int a,int b,int c){return gcd(gcd(a,b),c);}
inline ll lcm(ll a,ll b,ll c){return lcm(lcm(a,b),c);}
inline ll lcm(int a,int b,int c){return lcm(lcm(a,b),(ll)c);}

inline ll max(ll a,ll b){return (a>b)?a:b;}
inline int max(int a,int b){return (a>b)?a:b;}
inline double max(double a,double b){return (a>b)?a:b;}
inline ll max(ll a,ll b,ll c){return max(a,max(b,c));}
inline int max(int a,int b,int c){return max(a,max(b,c));}
inline double max(double a,double b,double c){return max(a,max(b,c));}
inline ll min(ll a,ll b){return (a<b)?a:b;}
inline int min(int a,int b){return (a<b)?a:b;}
inline double min(double a,double b){return (a<b)?a:b;}
inline ll min(ll a,ll b,ll c){return min(a,min(b,c));}
inline int min(int a,int b,int c){return min(a,min(b,c));}
inline double min(double a,double b,double c){return min(a,min(b,c));}

template<class T>
inline void getar(T a, int n, int m){ for (int i = 0; i < n; i++) for (int j = 0; j < m;++j) { scanf("%d", &a[i][j]); } }
inline void getar(int *a, int n){ for (int ii = 0; ii < n; ii++){ scanf("%d", a + ii); } }
inline void getar(pii *a, int n){ for (int ii = 0; ii < n; ii++){ scanf("%d%d", &a[ii].first, &a[ii].second); } }
inline void getar(ll *a, int n){ for (int ii = 0; ii < n; ii++){ scanf("%I64d", a + ii); } }

// Useful constants

#define INF         1011111111
#define EPS         (double)1e-8
#define mod         1000000007
#define PI          3.14159265358979
//*******************************************************************************/

int pr[100010];
vector<int> primes;
vector<int> d[100001];
vector<int> v[100001];
int t[100001];
bool used[100001];
int z[100001];
struct Comp
{
    bool operator()(const int&x, const int&y)
    {
        return t[x] < t[y];
    }
};
set<int, Comp> s;
vector<pii> ans;
bool cmp(const int &x, const int& y)
{
    return z[x] > z[y];
}
int main()
{
    int n;
    cin >> n;
    for (int i = 2; i <= n; ++i)
    {
        if (pr[i] == 0)
        {
            pr[i] = i;
            primes.push_back(i);
        }
        for (int x : primes)
        {
            if (x * i > n) break;
            if (pr[i] < x) break;
            pr[x * i] = x;
        }
    }
    for (int i = n; i >= 2; --i)
    {
        int x = i;
        while (x != 1){
            int p = pr[x];
            d[i].push_back(p);
            while (pr[x] == p)
            {
                x /= p;
            }
            z[i] += n / p;
            v[p].push_back(i);
        }
    }
    for (int i = 2; i <= n; ++i)
    {
        if (v[i].size() > 1)
        {
            sort(all(v[i]), cmp);
            //DBN(i, v[i]);
            t[i] = v[i].size();
            s.insert(i);
        }
    }
    while (!s.empty())
    {
        int p = *s.begin();
        s.erase(s.begin());

        int x = 0;
        int y = 0;
        for (int i = v[p].size() - 1; i >= 0; --i)
        {
            if (y) break;
            int val = v[p][i];
            if (!used[val])
            {
                if (!x) x = val;
                else y = val;
            }
            v[p].pop_back();
        }
        ans.push_back({ x, y });
        for (int p : d[x])
        {
            t[p]--;
        }
        for (int p : d[y])
        {
            t[p]--;
        }
        if (t[p] > 1)
            s.insert(p);
    }
    cout << ans.size() << '\n';
    for (pii p : ans)
    {
        cout << p.first << ' ' << p.second << '\n';
    }
    return 0;
}