Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Matrix Multiplication

Write a program which reads a $n \times m$ matrix $A$ and a $m \times l$ matrix $B$, and prints their product, a $n \times l$ matrix $C$. An element of matrix $C$ is obtained by the following formula:

\[
c_{ij} = \sum_{k=1}^m a_{ik}b_{kj}
\]

where $a_{ij}$, $b_{ij}$ and $c_{ij}$ are elements of $A$, $B$ and $C$ respectively.

Input

In the first line, three integers $n$, $m$ and $l$ are given separated by space characters

In the following lines, the $n \times m$ matrix $A$ and the $m \times l$ matrix $B$ are given.

Output

Print elements of the $n \times l$ matrix $C$ ($c_{ij}$). Print a single space character between adjacent elements.

Constraints

$1 \leq n, m, l \leq 100$

$0 \leq a_{ij}, b_{ij} \leq 10000$

Sample Input

3 2 3
1 2
0 3
4 5
1 2 1
0 3 2

Sample Output

1 8 5
0 9 6
4 23 14

Note

      解説

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ITP1_7_D
{
    class Program
    {
        static void Main(string[] args)
        {
            // 行列A：n×m
            // 行列B：m×l
            // 行列A×行列B=行列C：n×l　←　Cを出力するプログラム
            //各要素：a(ij)、b(ij)、c(ij)

            //1行目(n、m、l)を取得する
            long[] info = Console.ReadLine().Split(' ').Select(long.Parse).ToArray();
            long n = info[0];
            long m = info[1];
            long l = info[2];

            //行列A、B、Cを2次元配列として宣言
            //型[,] 配列名 = new 型[縦の要素数, 横の要素数]
            long[,] ranksA = new long[n, m];
            long[,] ranksB = new long[m, l];
            long[,] ranksC = new long[n, l];

            //行列A、Bの要素を受け取る配列の宣言と初期化
            long[] rowA = new long[m];
            long[] rowB = new long[l];

            //下記for文で用いる繰り返し回数の初期化
            long i1 = 0;
            long i2 = 0;
            long i3 = 0;
            long i4 = 0;
            long i5 = 0;
            long i6 = 0;
            long i7 = 0;

            //行列Aを2次元配列に代入
            for (i1 = 0; i1 < n; i1++)                                                       //n行分繰り返す処理
            {
                rowA = Console.ReadLine().Split(' ').Select(long.Parse).ToArray();           //行列の一行を要素に分解し、配列にする

                for (i2 = 0; i2 < m; i2++)                                                  //n列分繰り返す処理
                {
                    ranksA[i1, i2] = rowA[i2];
                }

            }

            //行列Bを2次元配列に代入
            for (i3 = 0; i3 < m; i3++)
            {
                rowB = Console.ReadLine().Split(' ').Select(long.Parse).ToArray();

                for (i4 = 0; i4 < l; i4++)
                {
                    ranksB[i3, i4] = rowB[i4];
                }
            }

            //行列A×行列Bの答えを行列Cに代入する処理
            for (i5 = 0; i5 < n; i5++)
            {
                for (i6 = 0; i6 < l; i6++)
                {
                    for (i7 = 0; i7 < m; i7++)
                    {
                        ranksC[i5, i6] += ranksA[i5, i7] * ranksB[i7, i6];
                    }
                }
            }
            //行列Cを出力する
            for (i5 = 0; i5 < n; i5++)
            {
                for (i6 = 0; i6 < l - 1; i6++)
                {
                    Console.Write(ranksC[i5, i6].ToString());

                    Console.Write(" ");
                }
                Console.WriteLine(ranksC[i5,i6]);
            }
        }

    }
}