Problem: Let's define the cost of a string s as the number of index pairs i and j (1 ≤ i < j < |s|) such that s_i = s_j and s_{i+1} = s_{j+1}.

You are given two positive integers n and k. Among all strings with length n that contain only the first k characters of the Latin alphabet, find a string with minimum possible cost. If there are multiple such strings with minimum cost — find any of them.

Input

The only line contains two integers n and k (1 ≤ n ≤ 2 ⋅ 10^5; 1 ≤ k ≤ 26).

Output

Print the string s such that it consists of n characters, each its character is one of the k first Latin letters, and it has the minimum possible cost among all these strings. If there are multiple such strings — print any of them.

Examples

Input


9 4


Output


aabacadbb


Input


5 1


Output


aaaaa

Input


10 26


Output


codeforces

Solution (in JAVA):

Solution:
import java.io.*;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;

public class Main {

    public static void main(String[] args) {

        Parser parser = Parser.getInstance();
        int t = 1;
        for (int i = 1; i <= t; i++) {
            Problem problem = new Problem();
            problem.solve(i);
        }
    }
}

class Problem {
    private static final Parser parser = Parser.getInstance();
    private static final Printer printer = Printer.getInstance();

    public Problem() {

    }

    public void solve() {
    }

    public void solve(int testNum) {
        int n = parser.parseInt();
        int k = parser.parseInt();

        if(k == 1) {
            System.out.println("a".repeat(n));
            return;
        }
        if(n == 1) {
            System.out.println("a");
            return;
        }

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("aa");
        int[][] costs = new int[26][26];
        costs[0][0] = 1;
        int last = 0;

        for(int i = 0; i < n - 2; i++) {
            int select = -1;
            int minCost = Integer.MAX_VALUE;
            for(int j = 0; j < k; j++) {
                if(minCost > costs[last][j]) {
                    select = j;
                    minCost = costs[last][j];
                } else if(minCost == costs[last][j]) {
                    select = get(costs, select, j, k);
                }
            }
            costs[last][select] += 1;
            stringBuilder.append((char)('a' + select));
            last = select;
        }
        System.out.println(stringBuilder);
    }

    private int get(int[][] costs, int a, int b, int k) {
        int aMinCost = Integer.MAX_VALUE;
        for(int i = 0; i < k; i++) {
            aMinCost = Math.min(aMinCost, costs[a][i]);
        }

        int bMinCost = Integer.MAX_VALUE;
        for(int i = 0; i < k; i++) {
            bMinCost = Math.min(bMinCost, costs[b][i]);
        }

        if(aMinCost < bMinCost) {
            return a;
        }

        return b;
    }
}

class SegmentTree {
    private final int size;
    private final long[] data;
    private final long[] lazy;
    private final BiFunction<Long, Long, Long> updateFunction;

    public SegmentTree(long[] array, BiFunction<Long, Long, Long> updateFunction) {
        size = array.length;
        data = new long[size * 4];
        lazy = new long[size * 4];
        this.updateFunction = updateFunction;
        init(array, 1, 0, size - 1);
    }

    private long init(long[] array, int node, int start, int end) {
        if (start == end) {
            return data[node] = array[start];
        }
        int mid = (start + end) / 2;
        return data[node] = updateFunction.apply(init(array, node * 2, start, mid), init(array, node * 2 + 1, mid + 1, end));
    }

    public void updateRange(int l, int r, long diff) {
        updateRange(1, 0, size - 1, l, r, diff);
    }

    private void updateRange(int node, int start, int end, int l, int r, long diff) {
        propagation(node, start, end);
        if (isOutOfRange(start, end, l, r)) return;
        if (isAllIn(start, end, l, r)) {
            lazy[node] += diff;
            propagation(node, start, end);
            return;
        }

        int mid = (start + end) / 2;
        updateRange(node * 2, start, mid, l, r, diff);
        updateRange(node * 2 + 1, mid + 1, end, l, r, diff);
        data[node] = updateFunction.apply(data[node * 2], data[node * 2 + 1]);
    }

    public long get(int l, int r) {
        return get(1, 0, size - 1, l, r);
    }

    private long get(int node, int start, int end, int l, int r) {
        propagation(node, start, end);
        if (isOutOfRange(start, end, l, r)) return 0;
        if (isAllIn(start, end, l, r)) return data[node];
        int mid = (start + end) / 2;
        return updateFunction.apply(get(node * 2, start, mid, l, r), get(node * 2 + 1, mid + 1, end, l, r));
    }

    private void propagation(int node, int start, int end) {
        long v = lazy[node];
        data[node] = updateFunction.apply(data[node], (end - start + 1) * v);
        if (start != end) {
            lazy[node * 2] += v;
            lazy[node * 2 + 1] += v;
        }
        lazy[node] = 0;
    }

    private boolean isOutOfRange(int start, int end, int l, int r) {
        return l > end || r <= start;
    }

    private boolean isAllIn(int start, int end, int l, int r) {
        return l <= start && end < r;
    }
}

class MathUtil {

    public static List<Integer> getPrimes(int r) {
        if (r < 2) {
            return new ArrayList<>();
        }

        List<Integer> result = new ArrayList<>();
        result.add(2);
        boolean[] is = new boolean[r + 1];
        for (int i = 4; i <= r; i += 2) {
            is[i] = true;
        }
        for (int i = 3; i <= r; i += 2) {
            if (is[i]) continue;
            result.add(i);
            for (long j = (long) i * i; j <= r; j += i) {
                is[(int) j] = true;
            }
        }
        return result;
    }

    public static long gcd(long a, long b) {
        return b == 0 ? a : gcd(b, a % b);
    }

    public static long pow(long x, long y) {
        return pow(x, y, Function.identity());
    }

    public static long pow(long x, long y, long mod) {
        return pow(x, y, v -> v % mod);
    }

    private static long pow(long x, long y, Function<Long, Long> action) {
        long res = 1;
        long t = x;
        while (y > 0) {
            if ((y & 1) == 1) {
                res *= t;
                res = action.apply(res);
            }
            t *= t;
            t = action.apply(t);
            y /= 2;
        }
        return res;
    }
}

class DisjointSet {

    private final int[] f;
    private final int[] counts;
    private int size;

    public DisjointSet(int size) {
        this.size = size;
        this.f = new int[size];
        for (int i = 0; i < size; i++) {
            f[i] = i;
        }
        this.counts = new int[size];
        for (int i = 0; i < size; i++) {
            counts[i] = 1;
        }
    }

    public int find(int u) {
        if (f[u] == u) return u;
        return f[u] = find(f[u]);
    }

    public boolean merge(int u, int v) {
        u = find(u);
        v = find(v);
        if (u == v) return false;
        if (u > v) {
            int t = u;
            u = v;
            v = t;
        }
        f[u] = v;
        counts[v] += counts[u];
        return true;
    }

    public int getCounts(int v) {
        return counts[find(v)];
    }

    public void debug() {
        System.out.println(Arrays.toString(f));
    }
}

class IntPair {
    private int l;
    private int r;

    public IntPair(int l, int r) {
        this.l = l;
        this.r = r;
    }

    public int getL() {
        return l;
    }

    public void setL(int l) {
        this.l = l;
    }

    public int getR() {
        return r;
    }

    public void setR(int r) {
        this.r = r;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        IntPair pair = (IntPair) o;
        return l == pair.l &&
                r == pair.r;
    }

    @Override
    public int hashCode() {
        return Objects.hash(l, r);
    }
}

class Parser {
    private static final Parser PARSER = new Parser();
    private static final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    private StringTokenizer tokenizer;

    public int parseInt() {
        fill();
        return Integer.parseInt(tokenizer.nextToken());
    }

    public long parseLong() {
        fill();
        return java.lang.Long.parseLong(tokenizer.nextToken());
    }

    public double parseDouble() {
        fill();
        return Double.parseDouble(tokenizer.nextToken());
    }

    public String parseLine() {
        try {
            return reader.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    String parseString() {
        fill();
        return tokenizer.nextToken();
    }

    private void fill() {
        while (tokenizer == null || !tokenizer.hasMoreElements()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static Parser getInstance() {
        return PARSER;
    }
}

class Printer {
    private static final Printer PRINTER = new Printer();
    private static final StringBuilder sb = new StringBuilder();

    public <T> Printer append(T o) {
        sb.append(o);
        return PRINTER;
    }

    public void print() {
        System.out.print(sb.toString());
        sb.setLength(0);
    }

    public static Printer getInstance() {
        return PRINTER;
    }
}