// implicit randomized cartesian tree
#include <bits/stdc++.h>
using namespace std;

mt19937 rng (12345);

struct Node;
typedef Node * PNode;
PNode EMPTY;
struct Node
{
	int value;
	int size;
	PNode left;
	PNode right;

	Node (int value_)
	{
		value = value_;
		size = 1;
		left = right = EMPTY;
	}
};

void recalc (PNode t)
{
	if (t == EMPTY) return;
	t -> size = 1;
	t -> size += t -> left -> size;
	t -> size += t -> right -> size;
}

// t: 100
// t->left: 64
// t: 1
// t->right: 35

// k = 80:
// [0.99] -> [0..79] | [80..99]
pair <PNode, PNode> tsplit (PNode t, int k)
{
	if (t == EMPTY) return {EMPTY, EMPTY};
	int leftsize = t -> left -> size + 1;
	if (k - leftsize >= 0)
	{ // 100: 64 + 1 + 35
	  // k = 80 -> 80-64-1
		auto temp = tsplit (t -> right, k - leftsize);
		t -> right = temp.first;
		recalc (t);
		return {t, temp.second};
	}
	else
	{ // 100: 64 + 1 + 35
	  // k = 50 -> 50
	  // [0..49]=temp.first, [50..63]=temp.second
	  // [0..49] | [50..99] = [50..63], 64, [65..99]
		auto temp = tsplit (t -> left, k);
		t -> left = temp.second;
		recalc (t);
		return {temp.first, t};
	}
}

/*
bool tfind (PNode t, int xf)
{
	if (t == EMPTY) return false;
	if (t -> x == xf) return true;
	if (t -> x < xf)
	{
		return tfind (t -> right, xf);
	}
	else
	{
		return tfind (t -> left, xf);
	}
}
*/

PNode tmerge (PNode l, PNode r)
{
	if (l == EMPTY) return r;
	if (r == EMPTY) return l;
	// (100) 100/110       (10) 10/110
	if (rng () % (l -> size + r -> size) < (unsigned) l -> size)
	{ //               l
	  //             /   \ .
	  //    l->left         l->right  r
		l -> right = tmerge (l -> right, r);
		recalc (l);
		return l;
	}
	else
	{ //                   r
	  //                 /   \ .
	  //    l  r->left         r->right
		r -> left = tmerge (l, r -> left);
		recalc (r);
		return r;
	}
}

PNode tinsert (PNode t, int value, int pos)
{
	auto temp = tsplit (t, pos);
	auto cur = new Node (value);
	// temp.first | cur | temp.second
	auto m = tmerge (temp.first, cur);
	return tmerge (m, temp.second);
}

PNode trem (PNode t, int x)
{
	auto temp = tsplit (t, x);
	auto temp2 = tsplit (temp.second, x + 1);
	// temp.first (< x) | temp2.first (== x) | temp2.second (> x)
	return tmerge (temp.first, temp2.second);
}

void toutput (PNode t)
{
	if (t == EMPTY) return;
	toutput (t -> left);
	cout << " " << t -> value;
	toutput (t -> right);
}

void full_output (PNode t)
{
	cout << "[";
	toutput (t);
	cout << "]" << endl;
}

PNode root;

int main ()
{
	EMPTY = new Node (0x7FFFFFFF);
	EMPTY -> size = 0;
	EMPTY -> left = EMPTY;
	EMPTY -> right = EMPTY;

	ios_base::sync_with_stdio (false);
	cin.tie (0);
	cout.tie (0);

	root = EMPTY;
	int n;
	cin >> n;
	for (int i = 0; i < n / 2; i++)
	{
		int j = (i * 11111) % n + 1;
		root = tinsert (root, j, root -> size / 2);
	}
	full_output (root); cout << endl;
/*
	for (int i = 0; i < n; i++)
	{
		cout << i << ": " <<
		    (tfind (root, i) ? "YES" : "NO") << endl;
	}
*/
	return 0;
}













