#include<bits/stdc++.h>
// #include<atcoder/all>
using namespace std;
// using namespace atcoder;
using lint = long long;
using ulint = unsigned long long;
template<class T>using graph = vector<vector<T>>;
#define endl '\n'
int const INF = 1<<30;
lint const INF64 = 1LL<<61;
lint const mod = 1e9+7;
//long const mod = 998244353;
lint ceilDiv(lint x, lint y){if(x >= 0){return (x+y-1)/y;}else{return x/y;}}
lint floorDiv(lint x, lint y){if(x >= 0){return x/y;}else{return (x-y+1)/y;}}
lint Sqrt(lint x){lint upper = 1e9;lint lower = 0;while(upper - lower > 0){lint mid = (1+upper + lower)/2;if(mid * mid > x){upper = mid-1;}else{lower = mid;}}return upper;}
lint gcd(lint a,lint b){if(a<b)swap(a,b);if(a%b==0)return b;else return gcd(b,a%b);}
lint lcm(lint a,lint b){return (a / gcd(a,b)) * b;}
lint chmin(vector<lint>&v){lint ans = INF64;for(lint i:v){ans = min(ans, i);}return ans;}
lint chmax(vector<lint>&v){lint ans = -INF64;for(lint i:v){ans = max(ans, i);}return ans;}
double dist(double x1, double y1, double x2, double y2){return sqrt(pow(x1-x2, 2) + pow(y1-y2,2));}
vector<lint>prime;void makePrime(lint n){prime.push_back(2);for(lint i=3;i<=n;i+=2){bool chk = true;for(lint j=0;j<prime.size() && prime[j]*prime[j] <= i;j++){if(i % prime[j]==0){chk=false;break;}}if(chk)prime.push_back(i);}}

int main(){
    vector<int>v(100001,1);
    int tmp = 1;
    for(int i=1;i<=100000;i++){
        if(i < (1<<tmp))v[i] = tmp;
        else{
            tmp++;
            v[i] = tmp;
        }
    }
    int n;
    cin >> n;
    for(int i=1;i<=n;i++)cout << v[i] << " ";
}


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

typedef pair<int,int>  pint;
typedef pair<ll,ll>    pll;
typedef vector<int>    vint;
typedef vector<ll>     vll;
typedef vector<string> vstr;
typedef vector<pint>   vpint;
typedef vector<pll>    vpll;

#define vint2(v,n,m,init) vector<vector<int>> v(n, vector<int>(m, init))
#define vll2(v,n,m,init)  vector<vector<ll>>  v(n, vector<ll>(m, init))

#define rep(i,n)         for(ll i=(ll)0; i<(ll)n; i++)
#define REP(i,m,n)       for(ll i=(ll)m; i<(ll)n; i++)
#define arr(var, n)      vint var(n); rep(i,n){cin >> var[i];}
#define arrll(var, n)    vll var(n); rep(i,n){cin >> var[i];}
#define arrst(var, n)    vstr var(n); rep(i,n){cin >> var[i];}
#define ALL(var)         (var).begin(), (var).end()
#define sortall(var)     sort(ALL(var))
#define uniqueall(v)     v.erase(unique(v.begin(), v.end()), v.end());

#define prt(var)         cout << (var) << "\n"
#define prt2(v1, v2)     cout << (v1) << " " << (v2) << "\n"
#define prt3(v1, v2, v3) cout << (v1) << " " << (v2) << " " << (v3) << "\n"
#define prtd(n, var)     cout << fixed << setprecision(n) << (var) << "\n"
#define prtfill(n, var)  cout << setw(n) << setfill('0') << (var);
#define prtall(v)        rep(i,v.size()){cout<<v[i]<<(i!=v.size()-1?" ":"\n");}
template <typename T>
bool chmax(T &a, const T& b){if(a<b){a=b; return true;} return false;}
template <typename T>
bool chmin(T &a, const T& b){if(a>b){a=b; return true;} return false;}
ll gcd(ll a, ll b){ return b?gcd(b,a%b):a;}
ll lcm(ll a, ll b){ return a/gcd(a,b)*b;}
//----------------------------------------------------------------

int main(void) {
    int n;
    cin >> n;

    vint a(n+1, 1);
    for(int i=1; i<=n; i++){
        for(int j=2; i*j<=n; j++){
            if(a[i]==a[i*j]) a[i*j]++;
        }
    }

    // for(int i=1; i<n+1; i++){
    //     for(int j=1; j<n+1; j++){
    //         if(j%i==0 && j!=i && a[j]==a[i]) prt2(i, j);
    //     }
    // }

    //prtall(a);
    vint ans;
    rep(i,n){
        ans.push_back(a[i+1]);
    }

    prtall(ans);
}
