description: The only difference between this problem and D1 is that you don't have to provide the way to construct the answer in D1, but you have to do it in this problem.
  
  There's a table of n × m cells (n rows and m columns). The value of n ⋅ m is even.
  
  A domino is a figure that consists of two cells having a common side. It may be horizontal (one of the cells is to the right of the other) or vertical (one of the cells is above the other).
  
  You need to place nm/2 dominoes on the table so that exactly k of them are horizontal and all the other dominoes are vertical. The dominoes cannot overlap and must fill the whole table.
  
  Input
  
  The first line contains one integer t (1 ≤ t ≤ 10) — the number of test cases. Then t test cases follow.
  
  Each test case consists of a single line. The line contains three integers n, m, k (1 ≤ n,m ≤ 100, 0 ≤ k ≤ nm/2, n ⋅ m is even) — the count of rows, columns and horizontal dominoes, respectively.
  
  Output
  
  For each test case:
  
    * print "NO" if it's not possible to place the dominoes on the table in the described way; 
    * otherwise, print "YES" on a separate line, then print n lines so that each of them contains m lowercase letters of the Latin alphabet — the layout of the dominoes on the table. Each cell of the table must be marked by the letter so that for every two cells having a common side, they are marked by the same letters if and only if they are occupied by the same domino. I.e. both cells of the same domino must be marked with the same letter, but two dominoes that share a side must be marked with different letters. If there are multiple solutions, print any of them. 
  
  Example
  
  Input
  
  
  8
  4 4 2
  2 3 0
  3 2 3
  1 2 0
  2 4 2
  5 2 2
  2 17 16
  2 1 1
  
  
  Output
  
  
  YES
  accx
  aegx
  bega
  bdda
  YES
  aha
  aha
  YES
  zz
  aa
  zz
  NO
  YES
  aaza
  bbza
  NO
  YES
  bbaabbaabbaabbaay
  ddccddccddccddccy
  NO
solution: # ---------------------------iye ha aam zindegi---------------------------------------------
  import math
  import random
  import heapq,bisect
  import sys
  from collections import deque, defaultdict
  from fractions import Fraction
  import sys
  import threading
  from collections import defaultdict
  threading.stack_size(10**8)
  mod = 10 ** 9 + 7
  mod1 = 998244353
  
  # ------------------------------warmup----------------------------
  import os
  import sys
  from io import BytesIO, IOBase
  sys.setrecursionlimit(300000)
  
  BUFSIZE = 8192
  
  
  class FastIO(IOBase):
      newlines = 0
  
      def __init__(self, file):
          self._fd = file.fileno()
          self.buffer = BytesIO()
          self.writable = "x" in file.mode or "r" not in file.mode
          self.write = self.buffer.write if self.writable else None
  
      def read(self):
          while True:
              b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
              if not b:
                  break
              ptr = self.buffer.tell()
              self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
          self.newlines = 0
          return self.buffer.read()
  
      def readline(self):
          while self.newlines == 0:
              b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
              self.newlines = b.count(b"\n") + (not b)
              ptr = self.buffer.tell()
              self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
          self.newlines -= 1
          return self.buffer.readline()
  
      def flush(self):
          if self.writable:
              os.write(self._fd, self.buffer.getvalue())
              self.buffer.truncate(0), self.buffer.seek(0)
  
  
  class IOWrapper(IOBase):
      def __init__(self, file):
          self.buffer = FastIO(file)
          self.flush = self.buffer.flush
          self.writable = self.buffer.writable
          self.write = lambda s: self.buffer.write(s.encode("ascii"))
          self.read = lambda: self.buffer.read().decode("ascii")
          self.readline = lambda: self.buffer.readline().decode("ascii")
  
  
  sys.stdin, sys.stdout = IOWrapper(sys.stdin), IOWrapper(sys.stdout)
  input = lambda: sys.stdin.readline().rstrip("\r\n")
  
  
  # -------------------game starts now----------------------------------------------------import math
  class TreeNode:
      def __init__(self, k, v):
          self.key = k
          self.value = v
          self.left = None
          self.right = None
          self.parent = None
          self.height = 1
          self.num_left = 1
          self.num_total = 1
  
  
  class AvlTree:
  
      def __init__(self):
          self._tree = None
  
      def add(self, k, v):
          if not self._tree:
              self._tree = TreeNode(k, v)
              return
          node = self._add(k, v)
          if node:
              self._rebalance(node)
  
      def _add(self, k, v):
          node = self._tree
          while node:
              if k < node.key:
                  if node.left:
                      node = node.left
                  else:
                      node.left = TreeNode(k, v)
                      node.left.parent = node
                      return node.left
              elif node.key < k:
                  if node.right:
                      node = node.right
                  else:
                      node.right = TreeNode(k, v)
                      node.right.parent = node
                      return node.right
              else:
                  node.value = v
                  return
  
      @staticmethod
      def get_height(x):
          return x.height if x else 0
  
      @staticmethod
      def get_num_total(x):
          return x.num_total if x else 0
  
      def _rebalance(self, node):
  
          n = node
          while n:
              lh = self.get_height(n.left)
              rh = self.get_height(n.right)
              n.height = max(lh, rh) + 1
              balance_factor = lh - rh
              n.num_total = 1 + self.get_num_total(n.left) + self.get_num_total(n.right)
              n.num_left = 1 + self.get_num_total(n.left)
  
              if balance_factor > 1:
                  if self.get_height(n.left.left) < self.get_height(n.left.right):
                      self._rotate_left(n.left)
                  self._rotate_right(n)
              elif balance_factor < -1:
                  if self.get_height(n.right.right) < self.get_height(n.right.left):
                      self._rotate_right(n.right)
                  self._rotate_left(n)
              else:
                  n = n.parent
  
      def _remove_one(self, node):
          """
          Side effect!!! Changes node. Node should have exactly one child
          """
          replacement = node.left or node.right
          if node.parent:
              if AvlTree._is_left(node):
                  node.parent.left = replacement
              else:
                  node.parent.right = replacement
              replacement.parent = node.parent
              node.parent = None
          else:
              self._tree = replacement
              replacement.parent = None
          node.left = None
          node.right = None
          node.parent = None
          self._rebalance(replacement)
  
      def _remove_leaf(self, node):
          if node.parent:
              if AvlTree._is_left(node):
                  node.parent.left = None
              else:
                  node.parent.right = None
              self._rebalance(node.parent)
          else:
              self._tree = None
          node.parent = None
          node.left = None
          node.right = None
  
      def remove(self, k):
          node = self._get_node(k)
          if not node:
              return
          if AvlTree._is_leaf(node):
              self._remove_leaf(node)
              return
          if node.left and node.right:
              nxt = AvlTree._get_next(node)
              node.key = nxt.key
              node.value = nxt.value
              if self._is_leaf(nxt):
                  self._remove_leaf(nxt)
              else:
                  self._remove_one(nxt)
              self._rebalance(node)
          else:
              self._remove_one(node)
  
      def get(self, k):
          node = self._get_node(k)
          return node.value if node else -1
  
      def _get_node(self, k):
          if not self._tree:
              return None
          node = self._tree
          while node:
              if k < node.key:
                  node = node.left
              elif node.key < k:
                  node = node.right
              else:
                  return node
          return None
  
      def get_at(self, pos):
          x = pos + 1
          node = self._tree
          while node:
              if x < node.num_left:
                  node = node.left
              elif node.num_left < x:
                  x -= node.num_left
                  node = node.right
              else:
                  return (node.key, node.value)
          raise IndexError("Out of ranges")
  
      @staticmethod
      def _is_left(node):
          return node.parent.left and node.parent.left == node
  
      @staticmethod
      def _is_leaf(node):
          return node.left is None and node.right is None
  
      def _rotate_right(self, node):
          if not node.parent:
              self._tree = node.left
              node.left.parent = None
          elif AvlTree._is_left(node):
              node.parent.left = node.left
              node.left.parent = node.parent
          else:
              node.parent.right = node.left
              node.left.parent = node.parent
          bk = node.left.right
          node.left.right = node
          node.parent = node.left
          node.left = bk
          if bk:
              bk.parent = node
          node.height = max(self.get_height(node.left), self.get_height(node.right)) + 1
          node.num_total = 1 + self.get_num_total(node.left) + self.get_num_total(node.right)
          node.num_left = 1 + self.get_num_total(node.left)
  
      def _rotate_left(self, node):
          if not node.parent:
              self._tree = node.right
              node.right.parent = None
          elif AvlTree._is_left(node):
              node.parent.left = node.right
              node.right.parent = node.parent
          else:
              node.parent.right = node.right
              node.right.parent = node.parent
          bk = node.right.left
          node.right.left = node
          node.parent = node.right
          node.right = bk
          if bk:
              bk.parent = node
          node.height = max(self.get_height(node.left), self.get_height(node.right)) + 1
          node.num_total = 1 + self.get_num_total(node.left) + self.get_num_total(node.right)
          node.num_left = 1 + self.get_num_total(node.left)
  
      @staticmethod
      def _get_next(node):
          if not node.right:
              return node.parent
          n = node.right
          while n.left:
              n = n.left
          return n
  
  
  # -----------------------------------------------binary seacrh tree---------------------------------------
  class SegmentTree1:
      def __init__(self, data, default=2*10**9, func=lambda a, b: min(a,b)):
          """initialize the segment tree with data"""
          self._default = default
          self._func = func
          self._len = len(data)
          self._size = _size = 1 << (self._len - 1).bit_length()
  
          self.data = [default] * (2 * _size)
          self.data[_size:_size + self._len] = data
          for i in reversed(range(_size)):
              self.data[i] = func(self.data[i + i], self.data[i + i + 1])
  
      def __delitem__(self, idx):
          self[idx] = self._default
  
      def __getitem__(self, idx):
          return self.data[idx + self._size]
  
      def __setitem__(self, idx, value):
          idx += self._size
          self.data[idx] = value
          idx >>= 1
          while idx:
              self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
              idx >>= 1
  
      def __len__(self):
          return self._len
  
      def query(self, start, stop):
          if start == stop:
              return self.__getitem__(start)
          stop += 1
          start += self._size
          stop += self._size
  
          res = self._default
          while start < stop:
              if start & 1:
                  res = self._func(res, self.data[start])
                  start += 1
              if stop & 1:
                  stop -= 1
                  res = self._func(res, self.data[stop])
              start >>= 1
              stop >>= 1
          return res
  
      def __repr__(self):
          return "SegmentTree({0})".format(self.data)
  
  
  # -------------------game starts now----------------------------------------------------import math
  class SegmentTree:
      def __init__(self, data, default=-1, func=lambda a, b: max(a,b)):
          """initialize the segment tree with data"""
          self._default = default
          self._func = func
          self._len = len(data)
          self._size = _size = 1 << (self._len - 1).bit_length()
  
          self.data = [default] * (2 * _size)
          self.data[_size:_size + self._len] = data
          for i in reversed(range(_size)):
              self.data[i] = func(self.data[i + i], self.data[i + i + 1])
  
      def __delitem__(self, idx):
          self[idx] = self._default
  
      def __getitem__(self, idx):
          return self.data[idx + self._size]
  
      def __setitem__(self, idx, value):
          idx += self._size
          self.data[idx] = value
          idx >>= 1
          while idx:
              self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
              idx >>= 1
  
      def __len__(self):
          return self._len
  
      def query(self, start, stop):
          if start == stop:
              return self.__getitem__(start)
          stop += 1
          start += self._size
          stop += self._size
  
          res = self._default
          while start < stop:
              if start & 1:
                  res = self._func(res, self.data[start])
                  start += 1
              if stop & 1:
                  stop -= 1
                  res = self._func(res, self.data[stop])
              start >>= 1
              stop >>= 1
          return res
  
      def __repr__(self):
          return "SegmentTree({0})".format(self.data)
  
  
  # -------------------------------iye ha chutiya zindegi-------------------------------------
  class Factorial:
      def __init__(self, MOD):
          self.MOD = MOD
          self.factorials = [1, 1]
          self.invModulos = [0, 1]
          self.invFactorial_ = [1, 1]
  
      def calc(self, n):
          if n <= -1:
              print("Invalid argument to calculate n!")
              print("n must be non-negative value. But the argument was " + str(n))
              exit()
          if n < len(self.factorials):
              return self.factorials[n]
          nextArr = [0] * (n + 1 - len(self.factorials))
          initialI = len(self.factorials)
          prev = self.factorials[-1]
          m = self.MOD
          for i in range(initialI, n + 1):
              prev = nextArr[i - initialI] = prev * i % m
          self.factorials += nextArr
          return self.factorials[n]
  
      def inv(self, n):
          if n <= -1:
              print("Invalid argument to calculate n^(-1)")
              print("n must be non-negative value. But the argument was " + str(n))
              exit()
          p = self.MOD
          pi = n % p
          if pi < len(self.invModulos):
              return self.invModulos[pi]
          nextArr = [0] * (n + 1 - len(self.invModulos))
          initialI = len(self.invModulos)
          for i in range(initialI, min(p, n + 1)):
              next = -self.invModulos[p % i] * (p // i) % p
              self.invModulos.append(next)
          return self.invModulos[pi]
  
      def invFactorial(self, n):
          if n <= -1:
              print("Invalid argument to calculate (n^(-1))!")
              print("n must be non-negative value. But the argument was " + str(n))
              exit()
          if n < len(self.invFactorial_):
              return self.invFactorial_[n]
          self.inv(n)  # To make sure already calculated n^-1
          nextArr = [0] * (n + 1 - len(self.invFactorial_))
          initialI = len(self.invFactorial_)
          prev = self.invFactorial_[-1]
          p = self.MOD
          for i in range(initialI, n + 1):
              prev = nextArr[i - initialI] = (prev * self.invModulos[i % p]) % p
          self.invFactorial_ += nextArr
          return self.invFactorial_[n]
  
  
  class Combination:
      def __init__(self, MOD):
          self.MOD = MOD
          self.factorial = Factorial(MOD)
  
      def ncr(self, n, k):
          if k < 0 or n < k:
              return 0
          k = min(k, n - k)
          f = self.factorial
          return f.calc(n) * f.invFactorial(max(n - k, k)) * f.invFactorial(min(k, n - k)) % self.MOD
  
  
  # --------------------------------------iye ha combinations ka zindegi---------------------------------
  def powm(a, n, m):
      if a == 1 or n == 0:
          return 1
      if n % 2 == 0:
          s = powm(a, n // 2, m)
          return s * s % m
      else:
          return a * powm(a, n - 1, m) % m
  
  
  # --------------------------------------iye ha power ka zindegi---------------------------------
  def sort_list(list1, list2):
      zipped_pairs = zip(list2, list1)
  
      z = [x for _, x in sorted(zipped_pairs)]
  
      return z
  
  
  # --------------------------------------------------product----------------------------------------
  def product(l):
      por = 1
      for i in range(len(l)):
          por *= l[i]
      return por
  
  
  # --------------------------------------------------binary----------------------------------------
  def binarySearchCount(arr, n, key):
      left = 0
      right = n - 1
  
      count = 0
  
      while (left <= right):
          mid = int((right + left) / 2)
  
          # Check if middle element is
          # less than or equal to key
          if (arr[mid] < key):
              count = mid + 1
              left = mid + 1
  
          # If key is smaller, ignore right half
          else:
              right = mid - 1
  
      return count
  
  
  # --------------------------------------------------binary----------------------------------------
  def countdig(n):
      c = 0
      while (n > 0):
          n //= 10
          c += 1
      return c
  def binary(x, length):
      y = bin(x)[2:]
      return y if len(y) >= length else "0" * (length - len(y)) + y
  
  def countGreater(arr, n, k):
      l = 0
      r = n - 1
  
      # Stores the index of the left most element
      # from the array which is greater than k
      leftGreater = n
  
      # Finds number of elements greater than k
      while (l <= r):
          m = int(l + (r - l) / 2)
          if (arr[m] >= k):
              leftGreater = m
              r = m - 1
  
          # If mid element is less than
          # or equal to k update l
          else:
              l = m + 1
  
      # Return the count of elements
      # greater than k
      return (n - leftGreater)
  
  class TrieNode:
      def __init__(self):
          self.children = [None] * 26
          self.isEndOfWord = False
  class Trie:
      def __init__(self):
          self.root = self.getNode()
      def getNode(self):
          return TrieNode()
      def _charToIndex(self, ch):
          return ord(ch) - ord('a')
      def insert(self, key):
          pCrawl = self.root
          length = len(key)
          for level in range(length):
              index = self._charToIndex(key[level])
              if not pCrawl.children[index]:
                  pCrawl.children[index] = self.getNode()
              pCrawl = pCrawl.children[index]
          pCrawl.isEndOfWord = True
      def search(self, key):
          pCrawl = self.root
          length = len(key)
          for level in range(length):
              index = self._charToIndex(key[level])
              if not pCrawl.children[index]:
                  return False
              pCrawl = pCrawl.children[index]
          return pCrawl != None and pCrawl.isEndOfWord
  #-----------------------------------------trie---------------------------------
  class Node:
      def __init__(self, data):
          self.data = data
          self.count=0
          self.left = None  # left node for 0
          self.right = None  # right node for 1
  class BinaryTrie:
      def __init__(self):
          self.root = Node(0)
      def insert(self, pre_xor):
          self.temp = self.root
          for i in range(31, -1, -1):
              val = pre_xor & (1 << i)
              if val:
                  if not self.temp.right:
                      self.temp.right = Node(0)
                  self.temp = self.temp.right
                  self.temp.count+=1
              if not val:
                  if not self.temp.left:
                      self.temp.left = Node(0)
                  self.temp = self.temp.left
                  self.temp.count += 1
          self.temp.data = pre_xor
      def query(self, xor):
          self.temp = self.root
          for i in range(31, -1, -1):
              val = xor & (1 << i)
              if not val:
                  if self.temp.left and self.temp.left.count>0:
                      self.temp = self.temp.left
                  elif self.temp.right:
                      self.temp = self.temp.right
              else:
                  if self.temp.right and self.temp.right.count>0:
                      self.temp = self.temp.right
                  elif self.temp.left:
                      self.temp = self.temp.left
              self.temp.count-=1
          return xor ^ self.temp.data
  # --------------------------------------------------binary-----------------------------------
  for ik in range(int(input())):
      n,m,k=map(int,input().split())
      def find(n,m,k):
          if n%2==1:
              k-=m//2
              if k<0:
                  return False
          poss=(m-m%2)//2
          if k%2==0 and k<=n*poss:
              return True
          return False
      if find(n,m,k)==True:
          print("YES")
          ans=[['' for i in range(m)]for j in range(n)]
          ch=0
          if n%2==1:
              for i in range(0,m,2):
                  ans[0][i]=chr(ch+97)
                  ans[0][i+1]=chr(ch+97)
                  ch+=1
                  ch%=26
              k-=m//2
          ch=0
          for i in range(n%2,n,2):
              for j in range(0,m,2):
                  while(i>0 and chr(ch+97)==ans[i-1][j]):
                      ch+=1
                      ch%=26
                  if k>0 and j<m-1:
                      ans[i][j] = chr(ch + 97)
                      ans[i][j+1] = chr(ch + 97)
                      ch=(ch+1)%26
                      ans[i+1][j] = chr(ch + 97)
                      ans[i+1][j+1] = chr(ch + 97)
                      k-=2
                      ch+=1
                      ch%=26
                  else:
                      break
          for i in range(n%2,n,2):
              for j in range(m):
                  ch=0
                  if ans[i][j]=='':
                      while((i>0 and chr(ch+97)==ans[i-1][j]) or (j>0 and chr(ch+97)==ans[i][j-1]) or (j>0 and chr(ch+97)==ans[i+1][j-1])):
                          ch+=1
                          ch%=26
                      ans[i][j]=chr(ch+97)
                      ans[i+1][j]=chr(ch+97)
                      ch+=1
                      ch%=26
          for i in range(n):
              print(*ans[i], sep="")
      else:
          print("NO")