#include<iostream>
#include<cstdio>
using namespace std;
int n,l,cnt=0; //cnt记录当前是第几个困难串
char s[81]; //最长穿串是80
bool dfs(int pos); //【】好好思考什么时候dfs要返回值什么时候不要 有了返回值具体又怎么设置!
bool judge(int pos);
void print(int pos);
int main()
{
while(scanf("%d %d",&n,&l)==2 &&n &&l )
{
cnt=0;
dfs(1);
}
return 0;
}
bool dfs(int pos)
{
if(cnt==n)
{
print(pos-1);
return true; //可以结束了的信号
}
for(int i=1;i<=l;i++)
{
char temp='A'+i-1;
s[pos]=temp;
if(judge(pos)) //是困难串
{
cnt++;
if(dfs(pos+1))
return true; //不是break了哈 break的话 返回上一层还要接着回溯下去
}
}
return false;
}
bool judge(int pos)
{
for(int i=1;i*2<=pos;i++)
{
bool chongfu=1;
for(int j=1;j<=i;j++) //从后面开始真的很妙啊,因为前cnt-1个字母已经检查过了,唯一要知道的就是含有最新一个字母的子串是否会有冲突
{
if(s[pos+1-j]!=s[pos+1-i-j])
{
chongfu=0;
break; //这个长度的相邻子串不重复 继续下一个
}
}
if(chongfu)
{
return false; //已经找到相邻的重复字串了...这是个容易的串
}
}
return true;
}
void print(int pos)
{
for(int i=1;i<=pos;i++)
{
cout<<s[i];
if(i%64==0) cout<<endl;
else if(i%4==0 && i!=pos) cout<<" ";
}
if(pos%64!=0)
cout<<endl;
cout<<pos<<endl;
}