本サイトAIZU ONLINE JUDGE ITP1_6_D へはこちらから
問題:ベクトルと行列の積
\(n×m\) の行列 \(A\) と、\(m×1\) の列ベクトル \(b\) を読み込み、 \(A\) と \(b\) の積を出力するプログラムを作成してください。
次のように \(m\) 個の数を縦に並べたものを \(m×1\) の列ベクトルと呼びます。
$$b = \left( \begin{array}{c} b_1 \\ b_2 \\ : \\ b_m \\ \end{array} \right)$$
次のように \(n\) 個の数を含む列ベクトルを \(m\) 個横に並べたものを \(n×m\) の行列と呼びます。
$$A = \left( \begin{array}{cccc} a_{11} & a_{12} & … & a_{1m} \\ a_{21} & a_{22} & … & a_{2m} \\ : & : & : & : \\ a_{n1} & a_{n2} & … & a_{nm} \\ \end{array} \right)$$
ベクトルまたは行列の中に含まれる数のことを要素と呼び、\(m×1\) の列ベクトル \(b\) の上から \(i\) 番目の要素は \(b_i (i = 1,2,…, m)\) 、\(n×m\) の行列 \(A\) には \(n×m\) 個の要素が含まれ、 \(i\)行 \(j\) 列目の要素は \(a_{ij} (i = 1, 2, …, n, j = 1, 2, …, m)\) で示されます。
\(n×m\) の行列 \(A\) と \(m×1\) の列ベクトル \(b\) の積は、 \(n×1\) の列ベクトル \(c\) となり、\(c\) の \(i\) 番目の要素 \(c_i\) は次の式で得られます:
$$c_i = \sum_{j=1}^m a_{ij}b_j = a_{i1}b_1 + a_{i2}b_2 + … + a_{im}b_m$$
Input
1行目に \(n\) と \(m\) が空白区切りで与えられます。続く \(n\) 行に行列 \(A\) の要素 \(a_{ij}\) が空白区切りで与えられます。続く \(m\) 行にベクトル \(b\) の要素 \(b_i\) がそれぞれ1行に与えられます。
Constraints
- 1≤ \(n\) ,\(m\)≤100
- 0≤\(b_i\) ,\(a_{ij}\) ≤1000
Output
出力は \(n\) 行からなります。ベクトル \(c\) の要素 \(c_i\) をそれぞれ1行に出力してください。
Sample Input
3 4
1 2 0 1
0 3 0 1
4 1 1 0
1
2
3
0
Sample Output
5
6
9
解答例
n, m = map(int, input().split())
A = [list(map(int, input().split())) for _ in range(n)]
b = [int(input()) for _ in range(m)]
for i in range(n):
sum = 0
for j in range(m):
sum += A[i][j] * b[j]
print(sum)
解説
以下のように解いていきます。
2つの整数(\(n\),\(m\))の読み込み
ここではmap関数を使用します。第二引数のinput().split()で空白区切りの文字列を取得した値を、一つずつint関数に当てはめてint型に変換、(\(n\)、\(m\))に設定していきます。
# input().split()で空白区切りの文字列を取得 → intに変換 → n, m に設定
n, m = map(int, input().split())
※サイト内「AIZU ONLINE JUDGE ITP1_1_Cをpythonで解いてみた」の、map関数とはにmap関数の使用方法が書かれておりますのでぜひご覧ください。
\(n×m\) の行列の読み込み
まず、map関数を使用し、m個の数字の入力を行います。第二引数のinput().split()で空白区切りの文字列を取得した値を、一つずつint関数に当てはめてint型に変換、さらに、list関数で囲みます。
続いて、for文のイテラブルにrange(n)を設定し、m個の数字の入力処理であるlist(map(int, input().split()))をn回行います。
これでm個の数字のかたまりが、n個のリストが作成されます。
# input().split()で空白区切りの文字列を取得 → intに変換 → list関数で囲み、リストとしてm個の数値を受け取る
# さらに【for _ in range(n)】でm個の数値の受け取りをn回行う
A = [list(map(int, input().split())) for _ in range(n)]
※サイト内「AIZU ONLINE JUDGE ITP1_6_Bをpythonで解いてみた」の、リスト内包表記とはにリスト内包表示の使用方法が書かれておりますのでよかったらご覧ください。
Sample Inputを例にすると以下のようにリストに設定されます。
# 入力
3 4
1 2 0 1
0 3 0 1
4 1 1 0
# 4個のリスト読み込みを3回繰り返し、リストに設定
[[1, 2, 0, 1], [0, 3, 0, 1], [4, 1, 1, 0]]
\(m×1\) の列ベクトルの読み込み
これも、2. \(n×m\) の行列の読み込みと同様に1つの整数の入力をm回繰り返し、リストに設定します。
# 1つの整数の入力をm回繰り返す
b = [int(input()) for _ in range(m)]
Sample Inputを例にすると以下のようにリストに設定されます。
# 入力
1
2
3
0
# 1つの整数の入力をm回繰り返し、リストに設定
[1, 2, 3, 0]
ベクトルと行列の積の表示
2、3で取得した行列とベクトルの積を表示します。
行列の積は以下のように求められます。
$$\begin{pmatrix}a & b \\\end{pmatrix} \begin{pmatrix}p & q \\r & s \\\end{pmatrix} = \begin{pmatrix}ap + br & aq+bs \\\end{pmatrix}$$
Sample Inputを例にすると以下のようになります。
# 列ベクトル
1
2
3
0
# 行列
1 2 0 1
0 3 0 1
4 1 1 0
# 列ベクトル × 行列 イメージ①
列ベクトル[1, 2, 3, 0] × 行列[[1, 2, 0, 1], [0, 3, 0, 1], [4, 1, 1, 0]]
# 列ベクトル × 行列 イメージ②
[1, 2, 3, 0] × [1, 2, 0, 1] = 5
[1, 2, 3, 0] × [0, 3, 0, 1] = 6
[1, 2, 3, 0] × [4, 1, 1, 0] = 9
# 列ベクトル × 行列 イメージ③
1×1 + 2×2 + 3×0 + 0×1 = 5
1×0 + 2×3 + 3×0 + 0×1 = 6
1×4 + 2×1 + 3×1 + 0×0 = 9
今回は2つのfor文を使用し、行列Aのi番目の各要素と列ベクトルbの要素の総和を求めて表示をn回繰り返します。
for i in range(n):
# sumをリセット
sum = 0
for j in range(m):
# 行列のi番目の要素のj番目 × 列ベクトルのj番目 を足し合わせる
sum += A[i][j] * b[j]
# 総和を表示
print(sum)
最後に、もう一度プログラムを確認してみましょう。
# input().split()で空白区切りの文字列を取得 → intに変換 → n, m に設定
n, m = map(int, input().split())
# input().split()で空白区切りの文字列を取得 → intに変換 → list関数で囲み、リストとしてm個の数値を受け取る
# さらに【for _ in range(n)】でm個の数値の受け取りをn回行う
A = [list(map(int, input().split())) for _ in range(n)]
# 1つの整数の入力をm回繰り返す
b = [int(input()) for _ in range(m)]
for i in range(n):
# sumをリセット
sum = 0
for j in range(m):
# 行列のi番目の要素のj番目 × 列ベクトルのj番目 を足し合わせる
sum += A[i][j] * b[j]
# 総和を表示
print(sum)
コメント