Problem:
Score : 400 points

Problem Statement

In this problem, we only consider strings consisting of lowercase English letters.

Strings s and t are said to be isomorphic when the following conditions are satisfied:

|s| = |t| holds.

For every pair i, j, one of the following holds:

s_i = s_j and t_i = t_j.

s_i \neq s_j and t_i \neq t_j.

For example, abcac and zyxzx are isomorphic, while abcac and ppppp are not.

A string s is said to be in normal form when the following condition is satisfied:

For every string t that is isomorphic to s, s \leq t holds. Here \leq denotes lexicographic comparison.

For example, abcac is in normal form, but zyxzx is not since it is isomorphic to abcac, which is lexicographically smaller than zyxzx.

You are given an integer N.
Print all strings of length N that are in normal form, in lexicographically ascending order.

Constraints

1 \leq N \leq 10

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N

Output

Assume that there are K strings of length N that are in normal form: w_1, \ldots, w_K in lexicographical order.
Output should be in the following format:

w_1
:
w_K

Sample Input 1

1

Sample Output 1

a

Sample Input 2

2

Sample Output 2

aa
ab

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

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Panasonic2020D
{
    class Input
    {
        /// <summary>
        /// 1行の入力を取得する
        /// </summary>
        /// <returns>文字列</returns>
        public void String(out string s)
        {
            s = Console.ReadLine();
        }

        /// <summary>
        /// 複数行の入力を取得
        /// </summary>
        /// <returns>文字列の配列</returns>
        public void String(long rowNumber, out string[] s)
        {
            s = new String[rowNumber];
            for (long i = 0; i < rowNumber; i++)
            {
                String(out s[i]);
            }
        }

        /// <summary>
        /// 1行の入力を取得
        /// </summary>
        /// <returns>int型の値</returns>
        public void Int(out int i)
        {
            string s;
            String(out s);
            i = int.Parse(s);
        }

        /// <summary>
        /// 1行の入力を取得
        /// </summary>
        /// <param name="a"></param>
        public void Long(out long a)
        {
            string s;
            String(out s);
            a = long.Parse(s);
        }

        /// <summary>
        /// 2つの整数が1行に書かれている入力を、2つのlongで受け取る
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        public void Long(out long a, out long b)
        {
            long[] lArr;
            Long(out lArr);
            a = lArr[0];
            b = lArr[1];
        }

        /// <summary>
        /// 3つの整数が1行に書かれている入力を、3つのlongで受け取る
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="c"></param>
        public void Long(out long a, out long b, out long c)
        {
            long[] lArr;
            Long(out lArr);
            a = lArr[0];
            b = lArr[1];
            c = lArr[2];
        }

        /// <summary>
        /// 4つの整数が1行に書かれている入力を、4つのlongで受け取る
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="c"></param>
        /// <param name="d"></param>
        public void Long(out long a, out long b, out long c, out long d)
        {
            long[] lArr;
            Long(out lArr);
            a = lArr[0];
            b = lArr[1];
            c = lArr[2];
            d = lArr[3];
        }

        public void Long(out long[] lArr)
        {
            lArr = Split().Select(long.Parse).ToArray();
        }

        public void Long(long rowNumber, out long[] lArr)
        {
            lArr = new long[rowNumber];
            for (long i = 0; i < rowNumber; i++)
            {
                Long(out lArr[i]);
            }
        }

        /// <summary>
        /// 2つの整数が複数行に書かれている入力を、2つのlong[]で受け取る
        /// </summary>
        /// <param name="rowNumber"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        public void Long(long rowNumber, out long[] a, out long[] b)
        {
            a = new long[rowNumber];
            b = new long[rowNumber];
            for (int i = 0; i < rowNumber; i++)
            {
                Long(out a[i], out b[i]);
            }
        }

        /// <summary>
        /// 3つの整数が複数行に書かれている入力を、3つのlong[]で受け取る
        /// </summary>
        /// <param name="rowNumber"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="c"></param>
        public void Long(long rowNumber, out long[] a, out long[] b, out long[] c)
        {
            a = new long[rowNumber];
            b = new long[rowNumber];
            c = new long[rowNumber];
            for (int i = 0; i < rowNumber; i++)
            {
                Long(out a[i], out b[i], out c[i]);
            }
        }

        /// <summary>
        /// 4つの整数が複数行に書かれている入力を、4つのlong[]で受け取る
        /// </summary>
        /// <param name="rowNumber"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="c"></param>
        /// <param name="d"></param>
        public void Long(long rowNumber, out long[] a, out long[] b, out long[] c, out long[] d)
        {
            a = new long[rowNumber];
            b = new long[rowNumber];
            c = new long[rowNumber];
            d = new long[rowNumber];
            for (int i = 0; i < rowNumber; i++)
            {
                Long(out a[i], out b[i], out c[i], out d[i]);
            }
        }

        /// <summary>
        /// h行w列のLongのmapを入力する
        /// </summary>
        /// <param name="h"></param>
        /// <param name="w"></param>
        /// <param name="a"></param>
        public void Long(long h, long w, out long[][] a)
        {
            a = new long[h][];
            for (long i = 0; i < h; i++)
            {
                Long(out a[i]);
            }
        }

        /// <summary>
        /// 1行の入力を取得
        /// </summary>
        /// <returns>double型の値</returns>
        public void Double(out double d)
        {
            string s;
            String(out s);
            d = double.Parse(s);
        }

        /// <summary>
        /// 1行の入力を取得
        /// </summary>
        /// <returns>double型の配列</returns>
        public void Double(out double[] dArr)
        {
            dArr = Split().Select(double.Parse).ToArray();
        }

        private IEnumerable<string> Split()
        {
            string s;
            String(out s);
            return s.Split(' ');
        }
    }

    class Program
    {
        public static void Main(string[] args)
        {
            StreamWriter sw = new StreamWriter(Console.OpenStandardOutput()) {AutoFlush = false};
            //  Console.SetOut(sw);
            Solver solver = new Solver();
            solver.Solve();
            //  Console.Out.Flush();
        }
    }

    class Solver
    {
        private Input input;

        public Solver()
        {
            input = new Input();
            input.Long(out N);
        }

        private long N;

        public void Solve()
        {
            if (N == 1)
            {
                Console.WriteLine("a");
                return;
            }

            write((int) N, 1, 1, 0);
            foreach (string a in ans)
            {
                Console.WriteLine(a.Substring(0, (int) N));
            }
        }

        private List<String> ans = new List<string>();

        public void write(
            int max,
            int depth,
            int chars,
            int a1,
            int a2 = 0,
            int a3 = 0,
            int a4 = 0,
            int a5 = 0,
            int a6 = 0,
            int a7 = 0,
            int a8 = 0,
            int a9 = 0,
            int a10 = 0
        )
        {
            if (max == depth)
            {
                char[] s =
                {
                    (char) (a1 + 'a'),
                    (char) (a2 + 'a'),
                    (char) (a3 + 'a'),
                    (char) (a4 + 'a'),
                    (char) (a5 + 'a'),
                    (char) (a6 + 'a'),
                    (char) (a7 + 'a'),
                    (char) (a8 + 'a'),
                    (char) (a9 + 'a'),
                    (char) (a10 + 'a'),
                };
                ans.Add(new string(s));
                return;
            }

            //Console.WriteLine('a' + a.Length);
            for (int c = 0; c < chars + 1; c++)
            {
                var cs = Math.Max(chars, c + 1);
                if (depth == 1)
                {
                    write(max, depth + 1, cs, a1, c);
                }
                else if (depth == 2)
                {
                    write(max, depth + 1, cs, a1, a2, c);
                }
                else if (depth == 3)
                {
                    write(max, depth + 1, cs, a1, a2, a3, c);
                }
                else if (depth == 4)
                {
                    write(max, depth + 1, cs, a1, a2, a3, a4, c);
                }
                else if (depth == 5)
                {
                    write(max, depth + 1, cs, a1, a2, a3, a4, a5, c);
                }
                else if (depth == 6)
                {
                    write(max, depth + 1, cs, a1, a2, a3, a4, a5, a6, c);
                }
                else if (depth == 7)
                {
                    write(max, depth + 1, cs, a1, a2, a3, a4, a5, a6, a7, c);
                }
                else if (depth == 8)
                {
                    write(max, depth + 1, cs, a1, a2, a3, a4, a5, a6, a7, a8, c);
                }
                else if (depth == 9)
                {
                    write(max, depth + 1, cs, a1, a2, a3, a4, a5, a6, a7, a8, a9, c);
                }
            }
        }
    }
}