Problem:
Score: 600 points

Problem Statement

AtCoder's head office consists of N rooms numbered 1 to N. For any two rooms, there is a direct passage connecting these rooms.

For security reasons, Takahashi the president asked you to set a level for every passage, which is a positive integer and must satisfy the following condition:

For each room i\ (1 \leq i \leq N), if we leave Room i, pass through some passages whose levels are all equal and get back to Room i, the number of times we pass through a passage is always even.

Your task is to set levels to the passages so that the highest level of a passage is minimized.

Constraints

N is an integer between 2 and 500 (inclusive).

Input

Input is given from Standard Input in the following format:

N

Output

Print one way to set levels to the passages so that the objective is achieved, as follows:

a_{1,2} a_{1,3} ... a_{1,N}
a_{2,3} ... a_{2,N}
.
.
.
a_{N-1,N}

Here a_{i,j} is the level of the passage connecting Room i and Room j.

If there are multiple solutions, any of them will be accepted.

Sample Input 1

3

Sample Output 1

1 2
1

The following image describes this output:

For example, if we leave Room 2, traverse the path 2 \to 3 \to 2 \to 3 \to 2 \to 1 \to 2 while only passing passages of level 1 and get back to Room 2, we pass through a passage six times.

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Text;

public class Program
{
    private int N;

    // 1 黒　-1 白
    private HashSet<int> B, W;
    private int[] Max;

    private HashSet<int>[] Edge;
    private int[][] Ans;

    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        Max = new int[N];
        Edge = new HashSet<int>[N];
        int cnt = 0;
        for (int i = 0; i < N; i++)
        {
            Edge[i] = new HashSet<int>();
            for (int j = 0; j < N; j++)
            {
                if (i != j)
                    Edge[i].Add(j);
            }
        }

        cnt = N * (N - 1) / 2;
        Ans = new int[N][];
        for (int i = 0; i < N; i++)
        {
            Ans[i] = new int[N];
        }

        while (cnt > 0)
        {
            int start;
            for (start = 0; start < N; start++)
            {
                if (Edge[start].Count > 0)
                    break;
            }

            B = new HashSet<int>();
            W = new HashSet<int>();
            int col = SetCol(start, 1) + 1;
            foreach (int i in B)
            {
                foreach (int j in W)
                {
                    Ans[i][j] = col;
                    Ans[j][i] = col;
                    Max[i] = col;
                    Max[j] = col;
                    cnt--;
                    Edge[i].Remove(j);
                    Edge[j].Remove(i);
                }
            }
        }

        var sb = new StringBuilder();
        for (int i = 0; i < N - 1; i++)
        {
            List<int> line = new List<int>();
            for (int j = i + 1; j < N; j++)
            {
                line.Add(Ans[i][j]);
            }

            sb.AppendLine(string.Join(" ", line));
        }
        Console.Write(sb.ToString());
    }

    private int SetCol(int pos, int col)
    {
        if (B.Contains(pos) || W.Contains(pos))
        {
            return -1;
        }

        if (col == 1)
            B.Add(pos);
        else if (col == -1)
            W.Add(pos);
        int res = Max[pos];
        foreach (int i in Edge[pos])
        {
            res = Math.Max(res, SetCol(i, col * -1));
        }

        return res;
    }


    public static void Main(string[] args)
    {
        new Program().Solve();
    }
}

class Scanner
{
    public Scanner()
    {
        _pos = 0;
        _line = new string[0];
    }

    const char Separator = ' ';
    private int _pos;
    private string[] _line;

    #region スペース区切りで取得

    public string Next()
    {
        if (_pos >= _line.Length)
        {
            _line = Console.ReadLine().Split(Separator);
            _pos = 0;
        }

        return _line[_pos++];
    }

    public int NextInt()
    {
        return int.Parse(Next());
    }

    public long NextLong()
    {
        return long.Parse(Next());
    }

    public double NextDouble()
    {
        return double.Parse(Next());
    }

    #endregion

    #region 型変換

    private int[] ToIntArray(string[] array)
    {
        var result = new int[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = int.Parse(array[i]);
        }

        return result;
    }

    private long[] ToLongArray(string[] array)
    {
        var result = new long[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = long.Parse(array[i]);
        }

        return result;
    }

    private double[] ToDoubleArray(string[] array)
    {
        var result = new double[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = double.Parse(array[i]);
        }

        return result;
    }

    #endregion

    #region 配列取得

    public string[] Array()
    {
        if (_pos >= _line.Length)
            _line = Console.ReadLine().Split(Separator);

        _pos = _line.Length;
        return _line;
    }

    public int[] IntArray()
    {
        return ToIntArray(Array());
    }

    public long[] LongArray()
    {
        return ToLongArray(Array());
    }

    public double[] DoubleArray()
    {
        return ToDoubleArray(Array());
    }

    #endregion
}