description: You are given an integer k and a string s that consists only of characters 'a' (a lowercase Latin letter) and '*' (an asterisk).
  
  Each asterisk should be replaced with several (from 0 to k inclusive) lowercase Latin letters 'b'. Different asterisk can be replaced with different counts of letter 'b'.
  
  The result of the replacement is called a BA-string.
  
  Two strings a and b are different if they either have different lengths or there exists such a position i that a_i ≠ b_i.
  
  A string a is lexicographically smaller than a string b if and only if one of the following holds: 
  
    * a is a prefix of b, but a ≠ b; 
    * in the first position where a and b differ, the string a has a letter that appears earlier in the alphabet than the corresponding letter in b. 
  
  
  
  Now consider all different BA-strings and find the x-th lexicographically smallest of them.
  
  Input
  
  The first line contains a single integer t (1 ≤ t ≤ 2000) — the number of testcases.
  
  The first line of each testcase contains three integers n, k and x (1 ≤ n ≤ 2000; 0 ≤ k ≤ 2000; 1 ≤ x ≤ 10^{18}). n is the length of string s.
  
  The second line of each testcase is a string s. It consists of n characters, each of them is either 'a' (a lowercase Latin letter) or '*' (an asterisk).
  
  The sum of n over all testcases doesn't exceed 2000. For each testcase x doesn't exceed the total number of different BA-strings. String s contains at least one character 'a'.
  
  Output
  
  For each testcase, print a single string, consisting only of characters 'b' and 'a' (lowercase Latin letters) — the x-th lexicographically smallest BA-string.
  
  Example
  
  Input
  
  
  3
  2 4 3
  a*
  4 1 3
  a**a
  6 3 20
  **a***
  
  
  Output
  
  
  abb
  abba
  babbbbbbbbb
  
  Note
  
  In the first testcase of the example, BA-strings ordered lexicographically are: 
  
    1. a
    2. ab
    3. abb
    4. abbb
    5. abbbb
  
  
  
  In the second testcase of the example, BA-strings ordered lexicographically are: 
  
    1. aa
    2. aba
    3. abba
  
  
  
  Note that string "aba" is only counted once, even though there are two ways to replace asterisks with characters 'b' to get it.
solution: import com.sun.source.tree.LiteralTree;
  
  import java.io.*;
  import java.util.*;
  
  import static java.lang.Math.*;
  import static java.lang.Math.ceil;
  import static java.util.Arrays.sort;
  
  public class C {
      static int mod = 1000000007;
  
      public static void main(String[] args) throws Exception {
  
          int t = ri();
          while (t-- > 0) {
              int n = (int) rnl();
              int k = (int) nl();
              long x = nl()-1;
              List<Integer> list = new ArrayList<>();
              char c[] = rcha();
              int len = 0;
              for (int i = 0; i < n; i++) {
                  if (c[i] == 'a' && i > 0 && c[i - 1] == '*') {
                      list.add(len);
                      len = 0;
                  } else if (c[i] == '*') {
                      len++;
                  }
              }
              if (len > 0) {
                  list.add(len);
              }
              int M = list.size();
              long[] size = new long[M];
              int[] arr = new int[M];
              for (int i = M - 1; i >= 0; i--) {
                  size[i] = ((long) list.get(i) * k + 1) * (i == M - 1 ? 1 : size[i + 1]);
                  if (size[i] > x || size[i] < 0) {
                      for (int j = i; j < M; j++) {
                          arr[j] = (int) (x / (j == M - 1 ? 1 : size[j + 1]));
                          x%= (j == M - 1 ? 1 : size[j + 1]);
                      }
                      break;
                  }
              }
              StringBuilder res = new StringBuilder("");
              int index = 0;
              for (int i = 0; i < n; i++) {
                  if (c[i] == '*') {
                      int j = i;
                      while (j + 1 < n && c[j + 1] == '*') {
                          j++;
                      }
                      for (int K = 0; K < arr[index]; K++) {
                          res.append("b");
                      }
                      i = j;
                      index++;
                  } else {
                      res.append("a");
                  }
              }
              prln(res);
          }
  
  
          close();
      }
  
  
      static class Nodes {
          int a;
          int b;
  
  
          Nodes(int a, int b) {
              this.a = a;
              this.b = b;
  
          }
  
          public boolean equals(Object o) {
              if (o instanceof Nodes) {
                  Nodes p = (Nodes) o;
                  return p.a == a;
              }
              return false;
          }
  
          public int hashCode() {
              return new Integer(a).hashCode() * 31 + new Integer(b).hashCode();
          }
      }
  
      static class DisjointSetUnion {
          int p[];
          int count[];
  
          public DisjointSetUnion(int n) {
              p = new int[n];
              count = new int[n];
              for (int i = 0; i < n; i++) {
                  count[i] = 1;
              }
              clear(n);
          }
  
          public void clear(int n) {
              for (int i = 0; i < n; i++) {
                  p[i] = i;
              }
          }
  
          public int get(int x) {
              return x != p[x] ? p[x] = get(p[x]) : x;
          }
  
          public int getCount(int x) {
              return count[x];
          }
  
          public boolean union(int a, int b) {
              a = get(a);
              b = get(b);
              p[a] = b;
              if (a != b) {
                  count[b] += count[a];
                  count[a] = 0;
              }
              return a != b;
          }
      }
  
      static BufferedReader __i = new BufferedReader(new InputStreamReader(System.in));
      static PrintWriter __o = new PrintWriter(new OutputStreamWriter(System.out));
      static StringTokenizer input;
      static boolean[] isPrime;
      static Random __r = new Random();
  
      // references
      // IBIG = 1e9 + 7
      // IMAX ~= 2e9
      // LMAX ~= 9e18
  
      // constants
      static final int IBIG = 1000000007;
      static final int IMAX = 2147483647;
      static final long LMAX = 9223372036854775807L;
  
      // math util
      static int minof(int a, int b, int c) {
          return min(a, min(b, c));
      }
  
      static int minof(int... x) {
          if (x.length == 1) return x[0];
          if (x.length == 2) return min(x[0], x[1]);
          if (x.length == 3) return min(x[0], min(x[1], x[2]));
          int min = x[0];
          for (int i = 1; i < x.length; ++i) if (x[i] < min) min = x[i];
          return min;
      }
  
      static long minof(long a, long b, long c) {
          return min(a, min(b, c));
      }
  
      static long minof(long... x) {
          if (x.length == 1) return x[0];
          if (x.length == 2) return min(x[0], x[1]);
          if (x.length == 3) return min(x[0], min(x[1], x[2]));
          long min = x[0];
          for (int i = 1; i < x.length; ++i) if (x[i] < min) min = x[i];
          return min;
      }
  
      static int maxof(int a, int b, int c) {
          return max(a, max(b, c));
      }
  
      static int maxof(int... x) {
          if (x.length == 1) return x[0];
          if (x.length == 2) return max(x[0], x[1]);
          if (x.length == 3) return max(x[0], max(x[1], x[2]));
          int max = x[0];
          for (int i = 1; i < x.length; ++i) if (x[i] > max) max = x[i];
          return max;
      }
  
      static long maxof(long a, long b, long c) {
          return max(a, max(b, c));
      }
  
      static long maxof(long... x) {
          if (x.length == 1) return x[0];
          if (x.length == 2) return max(x[0], x[1]);
          if (x.length == 3) return max(x[0], max(x[1], x[2]));
          long max = x[0];
          for (int i = 1; i < x.length; ++i) if (x[i] > max) max = x[i];
          return max;
      }
  
      static int powi(int a, int b) {
          if (a == 0) return 0;
          int ans = 1;
          while (b > 0) {
              if ((b & 1) > 0) ans *= a;
              a *= a;
              b >>= 1;
          }
          return ans;
      }
  
      static long powl(long a, int b) {
          if (a == 0) return 0;
          long ans = 1;
          while (b > 0) {
              if ((b & 1) > 0) ans *= a;
              a *= a;
              b >>= 1;
          }
          return ans;
      }
  
      static int fli(double d) {
          return (int) d;
      }
  
      static int cei(double d) {
          return (int) ceil(d);
      }
  
      static long fll(double d) {
          return (long) d;
      }
  
      static long cel(double d) {
          return (long) ceil(d);
      }
  
      static int gcd(int a, int b) {
          return b == 0 ? a : gcd(b, a % b);
      }
  
      static long gcd(long a, long b) {
          return b == 0 ? a : gcd(b, a % b);
      }
  
      static int[] exgcd(int a, int b) {
          if (b == 0) return new int[]{1, 0};
          int[] y = exgcd(b, a % b);
          return new int[]{y[1], y[0] - y[1] * (a / b)};
      }
  
      static long[] exgcd(long a, long b) {
          if (b == 0) return new long[]{1, 0};
          long[] y = exgcd(b, a % b);
          return new long[]{y[1], y[0] - y[1] * (a / b)};
      }
  
      static int randInt(int min, int max) {
          return __r.nextInt(max - min + 1) + min;
      }
  
      static long mix(long x) {
          x += 0x9e3779b97f4a7c15L;
          x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9L;
          x = (x ^ (x >> 27)) * 0x94d049bb133111ebL;
          return x ^ (x >> 31);
      }
  
      static void setTrue(int n) {
          for (int i = 0; i < n; i++) {
              isPrime[i] = true;
          }
      }
  
      static void prime(int n) {
          for (int i = 2; i * i < n; i++) {
              if (isPrime[i]) {
                  for (int j = i * i; j < n; j += i) isPrime[j] = false;
              }
          }
      }
  
      public static long lcm(long number1, long number2) {
          if (number1 == 0 || number2 == 0) {
              return 0;
          }
          long absNumber1 = Math.abs(number1);
          long absNumber2 = Math.abs(number2);
          long absHigherNumber = Math.max(absNumber1, absNumber2);
          long absLowerNumber = Math.min(absNumber1, absNumber2);
          long lcm = absHigherNumber;
          while (lcm % absLowerNumber != 0) {
              lcm += absHigherNumber;
          }
          return lcm;
      }
  
      // array util
      static void reverse(int[] a) {
          for (int i = 0, n = a.length, half = n / 2; i < half; ++i) {
              int swap = a[i];
              a[i] = a[n - i - 1];
              a[n - i - 1] = swap;
          }
      }
  
      static void reverse(long[] a) {
          for (int i = 0, n = a.length, half = n / 2; i < half; ++i) {
              long swap = a[i];
              a[i] = a[n - i - 1];
              a[n - i - 1] = swap;
          }
      }
  
      static void reverse(double[] a) {
          for (int i = 0, n = a.length, half = n / 2; i < half; ++i) {
              double swap = a[i];
              a[i] = a[n - i - 1];
              a[n - i - 1] = swap;
          }
      }
  
      static void reverse(char[] a) {
          for (int i = 0, n = a.length, half = n / 2; i < half; ++i) {
              char swap = a[i];
              a[i] = a[n - i - 1];
              a[n - i - 1] = swap;
          }
      }
  
      static void shuffle(int[] a) {
          int n = a.length - 1;
          for (int i = 0; i < n; ++i) {
              int ind = randInt(i, n);
              int swap = a[i];
              a[i] = a[ind];
              a[ind] = swap;
          }
      }
  
      static void shuffle(long[] a) {
          int n = a.length - 1;
          for (int i = 0; i < n; ++i) {
              int ind = randInt(i, n);
              long swap = a[i];
              a[i] = a[ind];
              a[ind] = swap;
          }
      }
  
      static void shuffle(double[] a) {
          int n = a.length - 1;
          for (int i = 0; i < n; ++i) {
              int ind = randInt(i, n);
              double swap = a[i];
              a[i] = a[ind];
              a[ind] = swap;
          }
      }
  
      static void rsort(int[] a) {
          shuffle(a);
          sort(a);
      }
  
      static void rsort(long[] a) {
          shuffle(a);
          sort(a);
      }
  
      static void rsort(double[] a) {
          shuffle(a);
          sort(a);
      }
  
      static int[] copy(int[] a) {
          int[] ans = new int[a.length];
          for (int i = 0; i < a.length; ++i) ans[i] = a[i];
          return ans;
      }
  
      static long[] copy(long[] a) {
          long[] ans = new long[a.length];
          for (int i = 0; i < a.length; ++i) ans[i] = a[i];
          return ans;
      }
  
      static double[] copy(double[] a) {
          double[] ans = new double[a.length];
          for (int i = 0; i < a.length; ++i) ans[i] = a[i];
          return ans;
      }
  
      static char[] copy(char[] a) {
          char[] ans = new char[a.length];
          for (int i = 0; i < a.length; ++i) ans[i] = a[i];
          return ans;
      }
  
      static void resetBoolean(boolean[] vis, int n) {
          for (int i = 0; i < n; i++) {
              vis[i] = false;
          }
      }
  
      static void setMinusOne(int[][] matrix) {
          int row = matrix.length;
          int col = matrix[0].length;
  
          for (int i = 0; i < row; i++) {
              for (int j = 0; j < col; j++) {
                  matrix[i][j] = -1;
              }
          }
  
      }
  
      // input
      static void r() throws IOException {
          input = new StringTokenizer(rline());
      }
  
      static int ri() throws IOException {
          return Integer.parseInt(rline().split(" ")[0]);
      }
  
      static long rl() throws IOException {
          return Long.parseLong(rline());
      }
  
      static double rd() throws IOException {
          return Double.parseDouble(rline());
      }
  
      static int[] ria(int n) throws IOException {
          int[] a = new int[n];
          r();
          for (int i = 0; i < n; ++i) a[i] = ni();
          return a;
      }
  
      static void ria(int[] a) throws IOException {
          int n = a.length;
          r();
          for (int i = 0; i < n; ++i) a[i] = ni();
      }
  
      static int[] riam1(int n) throws IOException {
          int[] a = new int[n];
          r();
          for (int i = 0; i < n; ++i) a[i] = ni() - 1;
          return a;
      }
  
      static void riam1(int[] a) throws IOException {
          int n = a.length;
          r();
          for (int i = 0; i < n; ++i) a[i] = ni() - 1;
      }
  
      static long[] rla(int n) throws IOException {
          long[] a = new long[n];
          r();
          for (int i = 0; i < n; ++i) a[i] = nl();
          return a;
      }
  
      static void rla(long[] a) throws IOException {
          int n = a.length;
          r();
          for (int i = 0; i < n; ++i) a[i] = nl();
      }
  
      static double[] rda(int n) throws IOException {
          double[] a = new double[n];
          r();
          for (int i = 0; i < n; ++i) a[i] = nd();
          return a;
      }
  
      static void rda(double[] a) throws IOException {
          int n = a.length;
          r();
          for (int i = 0; i < n; ++i) a[i] = nd();
      }
  
      static char[] rcha() throws IOException {
          return rline().toCharArray();
      }
  
      static void rcha(char[] a) throws IOException {
          int n = a.length, i = 0;
          for (char c : rline().toCharArray()) a[i++] = c;
      }
  
      static String rline() throws IOException {
          return __i.readLine();
      }
  
      static String n() {
          return input.nextToken();
      }
  
      static int rni() throws IOException {
          r();
          return ni();
      }
  
      static int ni() {
          return Integer.parseInt(n());
      }
  
      static long rnl() throws IOException {
          r();
          return nl();
      }
  
      static long nl() {
          return Long.parseLong(n());
      }
  
      static double rnd() throws IOException {
          r();
          return nd();
      }
  
      static double nd() {
          return Double.parseDouble(n());
      }
  
      // output
      static void pr(int i) {
          __o.print(i);
      }
  
      static void prln(int i) {
          __o.println(i);
      }
  
      static void pr(long l) {
          __o.print(l);
      }
  
      static void prln(long l) {
          __o.println(l);
      }
  
      static void pr(double d) {
          __o.print(d);
      }
  
      static void prln(double d) {
          __o.println(d);
      }
  
      static void pr(char c) {
          __o.print(c);
      }
  
      static void prln(char c) {
          __o.println(c);
      }
  
      static void pr(char[] s) {
          __o.print(new String(s));
      }
  
      static void prln(char[] s) {
          __o.println(new String(s));
      }
  
      static void pr(String s) {
          __o.print(s);
      }
  
      static void prln(String s) {
          __o.println(s);
      }
  
      static void pr(Object o) {
          __o.print(o);
      }
  
      static void prln(Object o) {
          __o.println(o);
      }
  
      static void prln() {
          __o.println();
      }
  
      static void pryes() {
          prln("yes");
      }
  
      static void pry() {
          prln("Yes");
      }
  
      static void prY() {
          prln("YES");
      }
  
      static void prno() {
          prln("no");
      }
  
      static void prn() {
          prln("No");
      }
  
      static void prN() {
          prln("NO");
      }
  
      static boolean pryesno(boolean b) {
          prln(b ? "yes" : "no");
          return b;
      }
  
      ;
  
      static boolean pryn(boolean b) {
          prln(b ? "Yes" : "No");
          return b;
      }
  
      static boolean prYN(boolean b) {
          prln(b ? "YES" : "NO");
          return b;
      }
  
      static void prln(int... a) {
          for (int i = 0, len = a.length - 1; i < len; pr(a[i]), pr(' '), ++i) ;
          if (a.length > 0) prln(a[a.length - 1]);
          else prln();
      }
  
      static void prln(long... a) {
          for (int i = 0, len = a.length - 1; i < len; pr(a[i]), pr(' '), ++i) ;
          if (a.length > 0) prln(a[a.length - 1]);
          else prln();
      }
  
      static void prln(double... a) {
          for (int i = 0, len = a.length - 1; i < len; pr(a[i]), pr(' '), ++i) ;
          if (a.length > 0) prln(a[a.length - 1]);
          else prln();
      }
  
      static <T> void prln(Collection<T> c) {
          int n = c.size() - 1;
          Iterator<T> iter = c.iterator();
          for (int i = 0; i < n; pr(iter.next()), pr(' '), ++i) ;
          if (n >= 0) prln(iter.next());
          else prln();
      }
  
      static void h() {
          prln("hlfd");
          flush();
      }
  
      static void flush() {
          __o.flush();
      }
  
      static void close() {
          __o.close();
      }
  
  }
  