using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("4 3");
WillReturn.Add("aaa");
WillReturn.Add("aaa");
WillReturn.Add("abc");
WillReturn.Add("abd");
//2
}
else if (InputPattern == "Input2") {
WillReturn.Add("2 5");
WillReturn.Add("aaaaa");
WillReturn.Add("abcde");
//4
}
else if (InputPattern == "Input3") {
WillReturn.Add("3 3");
WillReturn.Add("ooo");
WillReturn.Add("ooo");
WillReturn.Add("ooo");
//0
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static char[,] mBanArr;
static int UB_X;
static int UB_Y;
static HashSet<int> mXSet = new HashSet<int>();
static HashSet<int> mYSet = new HashSet<int>();
static void Main()
{
List<string> InputList = GetInputList();
mBanArr = CreateBanArr(InputList.Skip(1));
UB_X = mBanArr.GetUpperBound(0);
UB_Y = mBanArr.GetUpperBound(1);
var XList = new List<int>();
var YList = new List<int>();
for (int I = 0; I <= UB_X; I++) XList.Add(I);
for (int I = 0; I <= UB_Y; I++) YList.Add(I);
// X座標とY座標を、ランダマイズソート
foreach (int X in XList.OrderBy(pX => Guid.NewGuid())) mXSet.Add(X);
foreach (int Y in YList.OrderBy(pX => Guid.NewGuid())) mYSet.Add(Y);
while (true) {
HashSet<int> Set1 = ExecTate();
HashSet<int> Set2 = ExecYoko();
if (Set1.Count == 0 && Set2.Count == 0) {
break;
}
mYSet.ExceptWith(Set1);
mXSet.ExceptWith(Set2);
}
long Answer = mXSet.Count * mYSet.Count;
Console.WriteLine(Answer);
}
// Y座標ごとにチェックし、マークしたY座標のSetを返す
static HashSet<int> ExecTate()
{
var WillReturn = new HashSet<int>();
if (mXSet.Count >= 2) {
foreach (int EachY in mYSet) {
var CharSet = new HashSet<char>();
foreach (int EachX in mXSet) {
CharSet.Add(mBanArr[EachX, EachY]);
if (CharSet.Count == 2) break;
}
if (CharSet.Count == 1) {
WillReturn.Add(EachY);
}
}
}
return WillReturn;
}
// X座標ごとにチェックし、マークしたX座標のSetを返す
static HashSet<int> ExecYoko()
{
var WillReturn = new HashSet<int>();
if (mYSet.Count >= 2) {
foreach (int EachX in mXSet) {
var CharSet = new HashSet<char>();
foreach (int EachY in mYSet) {
CharSet.Add(mBanArr[EachX, EachY]);
if (CharSet.Count == 2) break;
}
if (CharSet.Count == 1) {
WillReturn.Add(EachX);
}
}
}
return WillReturn;
}
////////////////////////////////////////////////////////////////
// IEnumerable<string>をcharの2次元配列に設定する
////////////////////////////////////////////////////////////////
static char[,] CreateBanArr(IEnumerable<string> pStrEnum)
{
var StrList = pStrEnum.ToList();
if (StrList.Count == 0) {
return new char[0, 0];
}
int UB_X = StrList[0].Length - 1;
int UB_Y = StrList.Count - 1;
char[,] WillReturn = new char[UB_X + 1, UB_Y + 1];
for (int Y = 0; Y <= UB_Y; Y++) {
for (int X = 0; X <= UB_X; X++) {
WillReturn[X, Y] = StrList[Y][X];
}
}
return WillReturn;
}
}