1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.util.Scanner;

public class slo {

	private final static char[] LETTERS = new char[] { 'a', 'b', 'c' };
	private final static char[][] OTHER_LETTERS = new char[][] { { 'b', 'c' }, { 'a', 'c' }, { 'a', 'b' } };

	private long numberOfLetters; // n
	private long currentPosition; // na poczatku rowne k
	private StringBuilder resultBuilder = new StringBuilder();;
	private long currentUpperBound;

	public static void main(String[] args) throws IOException {

		Scanner in = new Scanner(System.in);
		long n = in.nextLong();
		long k = in.nextLong();

		slo s = new slo(n, k);
		System.out.println(s.getResult());

		in.close();
	}

	public slo(long n, long k) {
		this.numberOfLetters = n;
		this.currentPosition = k;
	}

	public String getResult() {

		try {
			int numberOfDigitsInCurrentPosition = Long.SIZE - Long.numberOfLeadingZeros(currentPosition);
			setUpUpperBound(numberOfDigitsInCurrentPosition);
			appendPrefixWithMinimalLetters(numberOfDigitsInCurrentPosition);
			currentPosition -= resultBuilder.length();
			if (resultBuilder.length() == 0) {
				makeStepForFirstLetter();
			}
			while (currentPosition > 0) {
				makeStepForNonFirstLetter();
			}
			return resultBuilder.toString();

		} catch (InvalidAlgorithmParameterException ex) {
			return "NIE";
		}
	}

	private void makeStepForFirstLetter() {
		long newUpperBound = currentUpperBound / 3;
		int whichLetter = (int) ((currentPosition - 1) / newUpperBound);
		resultBuilder.append(LETTERS[whichLetter]);
		currentPosition = currentPosition - whichLetter * newUpperBound - 1;
		currentUpperBound = newUpperBound;
	}

	private void makeStepForNonFirstLetter() {
		long newUpperBound = (currentUpperBound - 1) / 2;
		int whichLetter = (int) ((currentPosition - 1) / newUpperBound);
		resultBuilder.append(OTHER_LETTERS[resultBuilder.charAt(resultBuilder.length() - 1) - 'a'][whichLetter]);
		currentPosition = currentPosition - whichLetter * newUpperBound - 1;
		currentUpperBound = newUpperBound;
	}

	private void setUpUpperBound(int numberOfDigitsInPosition) throws InvalidAlgorithmParameterException {
		if (numberOfDigitsInPosition <= numberOfLetters) {
			currentUpperBound = (1L << numberOfDigitsInPosition) - 1;
		} else {
			currentUpperBound = 3 * ((1L << numberOfLetters) - 1);
			if (currentPosition > currentUpperBound) {
				throw new InvalidAlgorithmParameterException();
			}
		}
	}

	private void appendPrefixWithMinimalLetters(int numberOfDigitsInPosition) {
		long numberOfEasyToFindLetters = numberOfLetters + 1 - numberOfDigitsInPosition;
		for (long i = 0; i < numberOfEasyToFindLetters && i < currentPosition; ++i) {
			resultBuilder.append(LETTERS[(int) (i % 2)]);
		}
	}
}