using
System;
public
class
Program
{
static
long
[][] MatrixMultiply(
long
[][] a,
long
[][] b,
int
n,
int
l,
int
m)
{
long
[][] c =
new
long
[n][];
for
(
int
i = 0; i < n; i++)
c[i] =
new
long
[m];
for
(
int
i = 0; i < n; i++)
{
for
(
int
j = 0; j < m; j++)
{
c[i][j] = 0;
for
(
int
k = 0; k < l; k++)
{
c[i][j] += a[i][k] * b[k][j];
}
}
}
return
c;
}
static
long
[][] Strassen(
long
[][] a,
long
[][] b,
int
n,
int
l,
int
m)
{
if
(n == 1 || l == 1 || m == 1)
return
MatrixMultiply(a, b, n, l, m);
long
[][] c =
new
long
[n][];
for
(
int
i = 0; i < n; i++)
c[i] =
new
long
[m];
int
adjN = (n >> 1) + (n & 1);
int
adjL = (l >> 1) + (l & 1);
int
adjM = (m >> 1) + (m & 1);
long
[][][][] As =
new
long
[2][][][];
for
(
int
x = 0; x < 2; x++)
{
As[x] =
new
long
[2][][];
for
(
int
y = 0; y < 2; y++)
{
As[x][y] =
new
long
[adjN][];
for
(
int
i = 0; i < adjN; i++)
{
As[x][y][i] =
new
long
[adjL];
for
(
int
j = 0; j < adjL; j++)
{
int
I = i + (x & 1) * adjN;
int
J = j + (y & 1) * adjL;
As[x][y][i][j] = (I < n && J < l) ? a[I][J] : 0;
}
}
}
}
long
[][][][] Bs =
new
long
[2][][][];
for
(
int
x = 0; x < 2; x++)
{
Bs[x] =
new
long
[2][][];
for
(
int
y = 0; y < 2; y++)
{
Bs[x][y] =
new
long
[adjL][];
for
(
int
i = 0; i < adjL; i++)
{
Bs[x][y][i] =
new
long
[adjM];
for
(
int
j = 0; j < adjM; j++)
{
int
I = i + (x & 1) * adjL;
int
J = j + (y & 1) * adjM;
Bs[x][y][i][j] = (I < l && J < m) ? b[I][J] : 0;
}
}
}
}
long
[][][] s =
new
long
[10][][];
for
(
int
i = 0; i < 10; i++)
{
switch
(i)
{
case
0:
s[i] =
new
long
[adjL][];
for
(
int
j = 0; j < adjL; j++)
{
s[i][j] =
new
long
[adjM];
for
(
int
k = 0; k < adjM; k++)
{
s[i][j][k] = Bs[0][1][j][k] - Bs[1][1][j][k];
}
}
break
;
case
1:
s[i] =
new
long
[adjN][];
for
(
int
j = 0; j < adjN; j++)
{
s[i][j] =
new
long
[adjL];
for
(
int
k = 0; k < adjL; k++)
{
s[i][j][k] = As[0][0][j][k] + As[0][1][j][k];
}
}
break
;
case
2:
s[i] =
new
long
[adjN][];
for
(
int
j = 0; j < adjN; j++)
{
s[i][j] =
new
long
[adjL];
for
(
int
k = 0; k < adjL; k++)
{
s[i][j][k] = As[1][0][j][k] + As[1][1][j][k];
}
}
break
;
case
3:
s[i] =
new
long
[adjL][];
for
(
int
j = 0; j < adjL; j++)
{
s[i][j] =
new
long
[adjM];
for
(
int
k = 0; k < adjM; k++)
{
s[i][j][k] = Bs[1][0][j][k] - Bs[0][0][j][k];
}
}
break
;
case
4:
s[i] =
new
long
[adjN][];
for
(
int
j = 0; j < adjN; j++)
{
s[i][j] =
new
long
[adjL];
for
(
int
k = 0; k < adjL; k++)
{
s[i][j][k] = As[0][0][j][k] + As[1][1][j][k];
}
}
break
;
case
5:
s[i] =
new
long
[adjL][];
for
(
int
j = 0; j < adjL; j++)
{
s[i][j] =
new
long
[adjM];
for
(
int
k = 0; k < adjM; k++)
{
s[i][j][k] = Bs[0][0][j][k] + Bs[1][1][j][k];
}
}
break
;
case
6:
s[i] =
new
long
[adjN][];
for
(
int
j = 0; j < adjN; j++)
{
s[i][j] =
new
long
[adjL];
for
(
int
k = 0; k < adjL; k++)
{
s[i][j][k] = As[0][1][j][k] - As[1][1][j][k];
}
}
break
;
case
7:
s[i] =
new
long
[adjL][];
for
(
int
j = 0; j < adjL; j++)
{
s[i][j] =
new
long
[adjM];
for
(
int
k = 0; k < adjM; k++)
{
s[i][j][k] = Bs[1][0][j][k] + Bs[1][1][j][k];
}
}
break
;
case
8:
s[i] =
new
long
[adjN][];
for
(
int
j = 0; j < adjN; j++)
{
s[i][j] =
new
long
[adjL];
for
(
int
k = 0; k < adjL; k++)
{
s[i][j][k] = As[0][0][j][k] - As[1][0][j][k];
}
}
break
;
case
9:
s[i] =
new
long
[adjL][];
for
(
int
j = 0; j < adjL; j++)
{
s[i][j] =
new
long
[adjM];
for
(
int
k = 0; k < adjM; k++)
{
s[i][j][k] = Bs[0][0][j][k] + Bs[0][1][j][k];
}
}
break
;
}
}
long
[][][] p =
new
long
[7][][];
p[0] = Strassen(As[0][0], s[0], adjN, adjL, adjM);
p[1] = Strassen(s[1], Bs[1][1], adjN, adjL, adjM);
p[2] = Strassen(s[2], Bs[0][0], adjN, adjL, adjM);
p[3] = Strassen(As[1][1], s[3], adjN, adjL, adjM);
p[4] = Strassen(s[4], s[5], adjN, adjL, adjM);
p[5] = Strassen(s[6], s[7], adjN, adjL, adjM);
p[6] = Strassen(s[8], s[9], adjN, adjL, adjM);
for
(
int
i = 0; i < adjN; i++)
{
for
(
int
j = 0; j < adjM; j++)
{
c[i][j] = p[4][i][j] + p[3][i][j] - p[1][i][j] + p[5][i][j];
if
(j + adjM < m)
c[i][j + adjM] = p[0][i][j] + p[1][i][j];
if
(i + adjN < n)
c[i + adjN][j] = p[2][i][j] + p[3][i][j];
if
(i + adjN < n && j + adjM < m)
c[i + adjN][j + adjM] = p[4][i][j] + p[0][i][j] - p[2][i][j] - p[6][i][j];
}
}
for
(
int
x = 0; x < 2; x++)
{
for
(
int
y = 0; y < 2; y++)
{
for
(
int
i = 0; i < adjN; i++)
{
Array.Clear(As[x][y][i], 0, As[x][y][i].Length);
As[x][y][i] =
null
;
}
As[x][y] =
null
;
}
As[x] =
null
;
}
for
(
int
x = 0; x < 2; x++)
{
for
(
int
y = 0; y < 2; y++)
{
for
(
int
i = 0; i < adjL; i++)
{
Array.Clear(Bs[x][y][i], 0, Bs[x][y][i].Length);
Bs[x][y][i] =
null
;
}
Bs[x][y] =
null
;
}
Bs[x] =
null
;
}
for
(
int
i = 0; i < 10; i++)
{
switch
(i)
{
case
0:
case
3:
case
5:
case
7:
case
9:
for
(
int
j = 0; j < adjL; j++)
{
Array.Clear(s[i][j], 0, s[i][j].Length);
s[i][j] =
null
;
}
break
;
case
1:
case
2:
case
4:
case
6:
case
8:
for
(
int
j = 0; j < adjN; j++)
{
Array.Clear(s[i][j], 0, s[i][j].Length);
s[i][j] =
null
;
}
break
;
}
s[i] =
null
;
}
for
(
int
i = 0; i < 7; i++)
{
for
(
int
j = 0; j < (n >> 1); j++)
{
Array.Clear(p[i][j], 0, p[i][j].Length);
p[i][j] =
null
;
}
p[i] =
null
;
}
return
c;
}
public
static
void
Main(
string
[] args)
{
long
[][] matA =
new
long
[2][];
matA[0] =
new
long
[] { 1, 2, 3 };
matA[1] =
new
long
[] { 4, 5, 6 };
long
[][] matB =
new
long
[3][];
matB[0] =
new
long
[] { 7, 8 };
matB[1] =
new
long
[] { 9, 10 };
matB[2] =
new
long
[] { 11, 12 };
long
[][] matC = Strassen(matA, matB, 2, 3, 2);
for
(
int
i = 0; i < 2; i++)
{
for
(
int
j = 0; j < 2; j++)
{
Console.Write(matC[i][j] +
" "
);
}
Console.WriteLine();
}
}
}