#ifdef DEBUG
#  define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include "testlib.h"
#define ff first
#define ss second
#define szof(x) ((int)x.size())
#ifndef LOCAL
#  define cerr __get_ce
#endif

using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef unsigned long long ull;

using namespace __gnu_pbds;
template <typename T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename K, typename V> using ordered_map = tree<K, V, less<K>, rb_tree_tag, tree_order_statistics_node_update>;

int const INF = (int)1e9 + 1e3;
ll const INFL = (ll)1e18 + 1e6;

int main(int argc, char* argv[]) {
  registerGen(argc, argv, 1);

  int n = opt<int>("n");
  int e = opt<int>("e");
  int type = opt<int>("type");

  cout << n << " " << e << '\n';
  if (type == 1) {
    int lmin = opt<int>("lmin");
    int lmax = opt<int>("lmax");
    int skip = opt<int>("skip");
    vector<string> s(n);
    for (int i = 0; i < e; i++) {
      s[i] = string(rnd.next(lmin, lmax), char('a' + i));
    }
    if (skip) {
      swap(s[e - 1], s[rnd.next(e)]);
      s[e - 1] = "";
      e -= 1;
    }
    for (int i = e; i < n; i++) {
      int len = rnd.next(lmin, lmax);
      for (int j = 0; j < len; j++) {
        s[i] += char('a' + rnd.next(e));
      }
    }
    shuffle(s.begin(), s.end());
    for (int i = 0; i < n; i++) {
      cout << s[i] << '\n';
    }
  }
  if (type == 2) {
    int lmin = opt<int>("lmin");
    int lmax = opt<int>("lmax");
    vector<string> s(n);
    for (int i = 0; i < e; i++) {
      s[i] = string(rnd.next(lmin, lmax), char('a' + i));
    }
    int special = rnd.next(e);
    swap(s[e - 1], s[special]);
    s[e - 1] = "";
    for (int i = e - 1; i < n; i++) {
      int len = rnd.next(lmin, lmax);
      s[i] = string(len - 1, char('a' + special));
      char other;
      do {
        other = char('a' + rnd.next(e));
      } while (other == char('a' + special));
      s[i] += other;
    }
    shuffle(s.begin(), s.end());
    for (int i = 0; i < n; i++) {
      cout << s[i] << '\n';
    }
  }
  if (type == 3) {
    int lmin = opt<int>("lmin");
    int lmax = opt<int>("lmax");
    vector<string> s(n);
    int special1 = rnd.next(e);
    int special2 = rnd.next(e);
    while (special1 == special2) {
      special2 = rnd.next(e);
    }
    int ptr = 0;
    for (int i = 0; i < e; i++) {
      if (i == special1 || i == special2) {
        continue;
      }
      s[ptr++] = string(rnd.next(lmin, lmax), char('a' + i));
    }
    for (int i = ptr; i < n; i++) {
      int len = rnd.next(lmin, lmax);
      int special = (rnd.next(2) ? special1 : special2);
      s[i] = string(len - 1, char('a' + special));
      char other;
      do {
        other = char('a' + rnd.next(e));
      } while (other == char('a' + special));
      s[i] += other;
    }
    shuffle(s.begin(), s.end());
    for (int i = 0; i < n; i++) {
      cout << s[i] << '\n';
    }
  }

  return 0;
}