/**
n×m  の行列 A  と m×l  の行列 B  を入力し、それらの積である n×l  の
 を出力するプログラムを作成してください。行列 C  の各要素 c ij   は次の式で得られます：

 １行目に n 、m 、l  が空白区切りで与えられます。

続く行に n×m  の行列 A  と m×l  の行列 B  が与えられます。

 */

//スキャナつかうため

import java.util.Scanner;

public class Main {
	// プログラムのエントリポイント
	public static void main(String[] args) {
		// 入力ストリームの生成
		Scanner sc = new Scanner(System.in);
		// 3つの数値を受け取る
		int intN = sc.nextInt();
		int intM = sc.nextInt();
		int intL = sc.nextInt();
		// 受け取った数値で配列をつくる
		// Aの行列
		int[][] gyoua = new int[intN][intM];
		// Bの行列
		int[][] gyoub = new int[intM][intL];
		// Cの行列
		long[][] gyouc = new long[intN][intL];
		// 数値をAの配列の数受け取る
		for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intM; j++) {
				gyoua[i][j] = sc.nextInt();
			}
		}
		// Bの配列の数数値を受け取る
		for (int i = 0; i < intM; i++) {
			for (int j = 0; j < intL; j++) {
				gyoub[i][j] = sc.nextInt();
			}
		}
		// 計算
		for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intL; j++) {

				for (int k = 0; k < intM; k++) {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				}
				System.out.print(gyouc[i][j]);
				if (j != intL - 1) {
					// 空白
					System.out.print(" ");
				}
			}
			// 改行
			System.out.println();
		}

	}
} import java.util.Scanner; Scanner java.util public class Main {
	// プログラムのエントリポイント
	public static void main(String[] args) {
		// 入力ストリームの生成
		Scanner sc = new Scanner(System.in);
		// 3つの数値を受け取る
		int intN = sc.nextInt();
		int intM = sc.nextInt();
		int intL = sc.nextInt();
		// 受け取った数値で配列をつくる
		// Aの行列
		int[][] gyoua = new int[intN][intM];
		// Bの行列
		int[][] gyoub = new int[intM][intL];
		// Cの行列
		long[][] gyouc = new long[intN][intL];
		// 数値をAの配列の数受け取る
		for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intM; j++) {
				gyoua[i][j] = sc.nextInt();
			}
		}
		// Bの配列の数数値を受け取る
		for (int i = 0; i < intM; i++) {
			for (int j = 0; j < intL; j++) {
				gyoub[i][j] = sc.nextInt();
			}
		}
		// 計算
		for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intL; j++) {

				for (int k = 0; k < intM; k++) {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				}
				System.out.print(gyouc[i][j]);
				if (j != intL - 1) {
					// 空白
					System.out.print(" ");
				}
			}
			// 改行
			System.out.println();
		}

	}
} Main // プログラムのエントリポイント
	public static void main(String[] args) {
		// 入力ストリームの生成
		Scanner sc = new Scanner(System.in);
		// 3つの数値を受け取る
		int intN = sc.nextInt();
		int intM = sc.nextInt();
		int intL = sc.nextInt();
		// 受け取った数値で配列をつくる
		// Aの行列
		int[][] gyoua = new int[intN][intM];
		// Bの行列
		int[][] gyoub = new int[intM][intL];
		// Cの行列
		long[][] gyouc = new long[intN][intL];
		// 数値をAの配列の数受け取る
		for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intM; j++) {
				gyoua[i][j] = sc.nextInt();
			}
		}
		// Bの配列の数数値を受け取る
		for (int i = 0; i < intM; i++) {
			for (int j = 0; j < intL; j++) {
				gyoub[i][j] = sc.nextInt();
			}
		}
		// 計算
		for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intL; j++) {

				for (int k = 0; k < intM; k++) {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				}
				System.out.print(gyouc[i][j]);
				if (j != intL - 1) {
					// 空白
					System.out.print(" ");
				}
			}
			// 改行
			System.out.println();
		}

	} main {
		// 入力ストリームの生成
		Scanner sc = new Scanner(System.in);
		// 3つの数値を受け取る
		int intN = sc.nextInt();
		int intM = sc.nextInt();
		int intL = sc.nextInt();
		// 受け取った数値で配列をつくる
		// Aの行列
		int[][] gyoua = new int[intN][intM];
		// Bの行列
		int[][] gyoub = new int[intM][intL];
		// Cの行列
		long[][] gyouc = new long[intN][intL];
		// 数値をAの配列の数受け取る
		for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intM; j++) {
				gyoua[i][j] = sc.nextInt();
			}
		}
		// Bの配列の数数値を受け取る
		for (int i = 0; i < intM; i++) {
			for (int j = 0; j < intL; j++) {
				gyoub[i][j] = sc.nextInt();
			}
		}
		// 計算
		for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intL; j++) {

				for (int k = 0; k < intM; k++) {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				}
				System.out.print(gyouc[i][j]);
				if (j != intL - 1) {
					// 空白
					System.out.print(" ");
				}
			}
			// 改行
			System.out.println();
		}

	} Scanner sc = new Scanner(System.in); sc new Scanner(System.in) int intN = sc.nextInt(); intN sc.nextInt() sc.nextInt sc int intM = sc.nextInt(); intM sc.nextInt() sc.nextInt sc int intL = sc.nextInt(); intL sc.nextInt() sc.nextInt sc int[][] gyoua = new int[intN][intM]; gyoua new int[intN][intM] intN intM int[][] gyoub = new int[intM][intL]; gyoub new int[intM][intL] intM intL long[][] gyouc = new long[intN][intL]; gyouc new long[intN][intL] intN intL for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intM; j++) {
				gyoua[i][j] = sc.nextInt();
			}
		} int i = 0; int i = 0; i 0 i < intN i intN i++ i++ i {
			for (int j = 0; j < intM; j++) {
				gyoua[i][j] = sc.nextInt();
			}
		} {
			for (int j = 0; j < intM; j++) {
				gyoua[i][j] = sc.nextInt();
			}
		} for (int j = 0; j < intM; j++) {
				gyoua[i][j] = sc.nextInt();
			} int j = 0; int j = 0; j 0 j < intM j intM j++ j++ j {
				gyoua[i][j] = sc.nextInt();
			} {
				gyoua[i][j] = sc.nextInt();
			} gyoua[i][j] = sc.nextInt() gyoua[i][j] gyoua[i] gyoua i j sc.nextInt() sc.nextInt sc for (int i = 0; i < intM; i++) {
			for (int j = 0; j < intL; j++) {
				gyoub[i][j] = sc.nextInt();
			}
		} int i = 0; int i = 0; i 0 i < intM i intM i++ i++ i {
			for (int j = 0; j < intL; j++) {
				gyoub[i][j] = sc.nextInt();
			}
		} {
			for (int j = 0; j < intL; j++) {
				gyoub[i][j] = sc.nextInt();
			}
		} for (int j = 0; j < intL; j++) {
				gyoub[i][j] = sc.nextInt();
			} int j = 0; int j = 0; j 0 j < intL j intL j++ j++ j {
				gyoub[i][j] = sc.nextInt();
			} {
				gyoub[i][j] = sc.nextInt();
			} gyoub[i][j] = sc.nextInt() gyoub[i][j] gyoub[i] gyoub i j sc.nextInt() sc.nextInt sc for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intL; j++) {

				for (int k = 0; k < intM; k++) {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				}
				System.out.print(gyouc[i][j]);
				if (j != intL - 1) {
					// 空白
					System.out.print(" ");
				}
			}
			// 改行
			System.out.println();
		} int i = 0; int i = 0; i 0 i < intN i intN i++ i++ i {
			for (int j = 0; j < intL; j++) {

				for (int k = 0; k < intM; k++) {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				}
				System.out.print(gyouc[i][j]);
				if (j != intL - 1) {
					// 空白
					System.out.print(" ");
				}
			}
			// 改行
			System.out.println();
		} {
			for (int j = 0; j < intL; j++) {

				for (int k = 0; k < intM; k++) {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				}
				System.out.print(gyouc[i][j]);
				if (j != intL - 1) {
					// 空白
					System.out.print(" ");
				}
			}
			// 改行
			System.out.println();
		} for (int j = 0; j < intL; j++) {

				for (int k = 0; k < intM; k++) {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				}
				System.out.print(gyouc[i][j]);
				if (j != intL - 1) {
					// 空白
					System.out.print(" ");
				}
			} int j = 0; int j = 0; j 0 j < intL j intL j++ j++ j {

				for (int k = 0; k < intM; k++) {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				}
				System.out.print(gyouc[i][j]);
				if (j != intL - 1) {
					// 空白
					System.out.print(" ");
				}
			} {

				for (int k = 0; k < intM; k++) {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				}
				System.out.print(gyouc[i][j]);
				if (j != intL - 1) {
					// 空白
					System.out.print(" ");
				}
			} for (int k = 0; k < intM; k++) {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				} int k = 0; int k = 0; k 0 k < intM k intM k++ k++ k {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				} {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				} gyouc[i][j] += gyoua[i][k] * gyoub[k][j] gyouc[i][j] gyouc[i] gyouc i j gyoua[i][k] * gyoub[k][j] gyoua[i][k] gyoua[i] gyoua i k gyoub[k][j] gyoub[k] gyoub k j System.out.print(gyouc[i][j]) System.out.print System.out System System.out gyouc[i][j] gyouc[i] gyouc i j if (j != intL - 1) {
					// 空白
					System.out.print(" ");
				} j != intL - 1 j intL - 1 intL 1 {
					// 空白
					System.out.print(" ");
				} System.out.print(" ") System.out.print System.out System System.out " " System.out.println() System.out.println System.out System System.out String[] args args public class Main {
	// プログラムのエントリポイント
	public static void main(String[] args) {
		// 入力ストリームの生成
		Scanner sc = new Scanner(System.in);
		// 3つの数値を受け取る
		int intN = sc.nextInt();
		int intM = sc.nextInt();
		int intL = sc.nextInt();
		// 受け取った数値で配列をつくる
		// Aの行列
		int[][] gyoua = new int[intN][intM];
		// Bの行列
		int[][] gyoub = new int[intM][intL];
		// Cの行列
		long[][] gyouc = new long[intN][intL];
		// 数値をAの配列の数受け取る
		for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intM; j++) {
				gyoua[i][j] = sc.nextInt();
			}
		}
		// Bの配列の数数値を受け取る
		for (int i = 0; i < intM; i++) {
			for (int j = 0; j < intL; j++) {
				gyoub[i][j] = sc.nextInt();
			}
		}
		// 計算
		for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intL; j++) {

				for (int k = 0; k < intM; k++) {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				}
				System.out.print(gyouc[i][j]);
				if (j != intL - 1) {
					// 空白
					System.out.print(" ");
				}
			}
			// 改行
			System.out.println();
		}

	}
} public class Main {
	// プログラムのエントリポイント
	public static void main(String[] args) {
		// 入力ストリームの生成
		Scanner sc = new Scanner(System.in);
		// 3つの数値を受け取る
		int intN = sc.nextInt();
		int intM = sc.nextInt();
		int intL = sc.nextInt();
		// 受け取った数値で配列をつくる
		// Aの行列
		int[][] gyoua = new int[intN][intM];
		// Bの行列
		int[][] gyoub = new int[intM][intL];
		// Cの行列
		long[][] gyouc = new long[intN][intL];
		// 数値をAの配列の数受け取る
		for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intM; j++) {
				gyoua[i][j] = sc.nextInt();
			}
		}
		// Bの配列の数数値を受け取る
		for (int i = 0; i < intM; i++) {
			for (int j = 0; j < intL; j++) {
				gyoub[i][j] = sc.nextInt();
			}
		}
		// 計算
		for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intL; j++) {

				for (int k = 0; k < intM; k++) {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				}
				System.out.print(gyouc[i][j]);
				if (j != intL - 1) {
					// 空白
					System.out.print(" ");
				}
			}
			// 改行
			System.out.println();
		}

	}
} Main
/**
n×m  の行列 A  と m×l  の行列 B  を入力し、それらの積である n×l  の
 を出力するプログラムを作成してください。行列 C  の各要素 c ij   は次の式で得られます：

 １行目に n 、m 、l  が空白区切りで与えられます。

続く行に n×m  の行列 A  と m×l  の行列 B  が与えられます。

 */

//スキャナつかうため

import java.util.Scanner;

public class Main {
	// プログラムのエントリポイント
	public static void main(String[] args) {
		// 入力ストリームの生成
		Scanner sc = new Scanner(System.in);
		// 3つの数値を受け取る
		int intN = sc.nextInt();
		int intM = sc.nextInt();
		int intL = sc.nextInt();
		// 受け取った数値で配列をつくる
		// Aの行列
		int[][] gyoua = new int[intN][intM];
		// Bの行列
		int[][] gyoub = new int[intM][intL];
		// Cの行列
		long[][] gyouc = new long[intN][intL];
		// 数値をAの配列の数受け取る
		for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intM; j++) {
				gyoua[i][j] = sc.nextInt();
			}
		}
		// Bの配列の数数値を受け取る
		for (int i = 0; i < intM; i++) {
			for (int j = 0; j < intL; j++) {
				gyoub[i][j] = sc.nextInt();
			}
		}
		// 計算
		for (int i = 0; i < intN; i++) {
			for (int j = 0; j < intL; j++) {

				for (int k = 0; k < intM; k++) {
					// Cの配列に計算結果を入れていく
					gyouc[i][j] += gyoua[i][k] * gyoub[k][j];
				}
				System.out.print(gyouc[i][j]);
				if (j != intL - 1) {
					// 空白
					System.out.print(" ");
				}
			}
			// 改行
			System.out.println();
		}

	}
}