#include <bits/stdc++.h>
using namespace std;
template <class T>
inline T checkmin(T &a, T b) {
  return (a < b) ? a : a = b;
}
template <class T>
inline T checkmax(T &a, T b) {
  return (a > b) ? a : a = b;
}
template <class T>
T GCD(T a, T b) {
  if (a < 0) return GCD(-a, b);
  if (b < 0) return GCD(a, -b);
  return (a == 0) ? b : GCD(b % a, a);
}
template <class T>
T LCM(T a, T b) {
  if (a < 0) return LCM(-a, b);
  if (b < 0) return LCM(a, -b);
  return (a == 0 || b == 0) ? 0 : a / GCD(a, b) * b;
}
template <class T>
T ExtGCD(T a, T b, T &x, T &y) {
  if (a < 0) {
    T c = ExtGCD(-a, b, x, y);
    x = -x;
    return c;
  }
  if (b < 0) {
    T c = ExtGCD(a, -b, x, y);
    y = -y;
    return c;
  }
  if (a == 0) {
    x = 0, y = 1;
    return b;
  } else {
    T c = ExtGCD(b % a, a, y, x);
    x -= b / a * y;
    return c;
  }
}
template <class T>
inline T sqr(T X) {
  return X * X;
}
namespace Poor2 {
const int MaxiL = 11;
const int MaxiS = 60000;
const int MaxiN = 9;
int N, M;
int Pow3[MaxiL];
int Opt[MaxiN * MaxiN][MaxiS];
int From[MaxiN * MaxiN][MaxiS];
int Get(int S, int Pos) { return 0; }
void Run() {
  Pow3[0] = 1;
  for (int i = 1; i < MaxiL; ++i) Pow3[i] = Pow3[i - 1] * 3;
  memset(Opt, -1, sizeof(Opt));
  scanf("%d%d", &N, &M);
  Opt[0][0] = 0;
  for (int i = 0; i < N; ++i)
    for (int j = 0; j < M; ++j)
      for (int Sit = 0; Sit < Pow3[M + 1]; ++Sit)
        if (Opt[i * M + j][Sit] >= 0) {
          int L = (j == 0) ? 0 : Get(Sit, M);
          int U = Get(Sit, j);
          if (L > 0 && U > 0) continue;
        }
}
}  // namespace Poor2
namespace Poor {
const int MaxiL = 11;
const int MaxiN = 9;
const int TotDir = 4;
const int Dx[TotDir] = {-1, 0, 1, 0};
const int Dy[TotDir] = {0, -1, 0, 1};
int N, M, Best;
int Stack[MaxiN * MaxiN], Direct[MaxiN * MaxiN];
bool Vis[MaxiN * MaxiN];
bool Put[MaxiN][MaxiN];
char Out[MaxiN][MaxiN];
inline bool InRange(int X, int Y) { return X >= 0 && X < N && Y >= 0 && Y < M; }
inline bool Check(int X, int Y) { return !InRange(X, Y) || !Vis[X * M + Y]; }
bool Able(int Now, int Target) {
  if (Now == Target) return 1;
  int X = Stack[Now] / M, Y = Stack[Now] % M;
  for (int i = 0; i < TotDir; ++i)
    if (InRange(X - Dx[i] * 2, Y - Dy[i] * 2) &&
        !Put[X - Dx[i] * 2][Y - Dy[i] * 2]) {
      bool Flag = 1;
      for (int j = 0; j < TotDir; ++j)
        if (j != i &&
            (!InRange(X + Dx[j], Y + Dy[j]) || Put[X + Dx[j]][Y + Dy[j]])) {
          Flag = 0;
          break;
        }
      if (!Flag) continue;
      Put[X - Dx[i] * 2][Y - Dy[i] * 2] = 1;
      for (int j = 0; j < TotDir; ++j)
        if (j != i) Put[X + Dx[j]][Y + Dy[j]] = 1;
      Flag = Able(Now + 1, Target);
      Put[X - Dx[i] * 2][Y - Dy[i] * 2] = 0;
      for (int j = 0; j < TotDir; ++j)
        if (j != i) Put[X + Dx[j]][Y + Dy[j]] = 0;
      if (Flag) return 1;
    }
  return 0;
}
inline bool CanPut(int X, int Y, int i) {
  if (!Put[X][Y] && InRange(X - Dx[i] * 2, Y - Dy[i] * 2) &&
      !Put[X - Dx[i] * 2][Y - Dy[i] * 2]) {
    bool Flag = 1;
    for (int j = 0; j < TotDir; ++j)
      if (j != i &&
          (!InRange(X + Dx[j], Y + Dy[j]) || Put[X + Dx[j]][Y + Dy[j]])) {
        Flag = 0;
        break;
      }
    return Flag;
  }
  return 0;
}
inline void DoPut(int X, int Y, int i) {
  Put[X][Y] = 1;
  Put[X - Dx[i] * 2][Y - Dy[i] * 2] = 1;
  for (int j = 0; j < TotDir; ++j)
    if (j != i) Put[X + Dx[j]][Y + Dy[j]] = 1;
}
inline void UndoPut(int X, int Y, int i) {
  Put[X][Y] = 0;
  Put[X - Dx[i] * 2][Y - Dy[i] * 2] = 0;
  for (int j = 0; j < TotDir; ++j)
    if (j != i) Put[X + Dx[j]][Y + Dy[j]] = 0;
}
inline void Draw(int X, int Y, int i, char Ch) {
  Out[X][Y] = Ch;
  Out[X - Dx[i] * 2][Y - Dy[i] * 2] = Ch;
  for (int j = 0; j < TotDir; ++j)
    if (j != i) Out[X + Dx[j]][Y + Dy[j]] = Ch;
}
void DFS(int Step, int State) {
  if (State == N * M) {
    if (Step > Best) {
      Best = Step;
      for (int i = 0; i < N; ++i)
        for (int j = 0; j < M; ++j) Out[i][j] = '.';
      for (int k = 0; k < Step; ++k)
        Draw(Stack[k] / M, Stack[k] % M, Direct[k], 'A' + k);
    }
    return;
  }
  if (N * M >= 50 && Step + (N * M - State + 1) / 5 <= Best) return;
  DFS(Step, State + 1);
  if (State == 0 || State == M - 1 || State == (N - 1) * M ||
      State == N * M - 1)
    return;
  int X = State / M, Y = State % M;
  if (Check(X - 1, Y) && Check(X, Y - 1) && Check(X - 1, Y - 1) &&
      Check(X - 1, Y + 1)) {
    Stack[Step] = State;
    Vis[State] = 1;
    for (int i = 0; i < TotDir; ++i)
      if (CanPut(X, Y, i)) {
        Direct[Step] = i;
        DoPut(X, Y, i);
        DFS(Step + 1, State + 1);
        UndoPut(X, Y, i);
      }
    Vis[State] = 0;
  }
}
void Run() {
  scanf("%d%d", &N, &M);
  Best = -1;
  DFS(0, 0);
  cout << Best << endl;
  for (int i = 0; i < N; ++i) {
    for (int j = 0; j < M; ++j) cout << Out[i][j];
    cout << endl;
  }
}
}  // namespace Poor
int main() { Poor::Run(); }
