行列、線形代数の基本的な概念の一つ。m×n個のm×n行列は、行列番号に配置された数m行n列です。コンピュータでは、マトリックスは、実際には二次元アレイです。従って、マトリクス構造として定義することができます。
マトリックス構造体
{
int型MAT [110] [110]; //行列要素記憶されている
int型の行、列、行列の//サイズ、行の行、列列
}。
行列の乗算は、基本的な行列演算です。
m×n行列をさせ、Bをk×n行列であり、次にその生成物ABは、K行列×Mである(時々・Bに示します)。
I番目のAは、・j列目のBの積行列要素は番号を乗算するn個の第2行列B nの第i行j列に行列Aの数nに対応して得られる行製品の合計。すなわち:
なお:行列行列Bの行と列の同じ数は、×B行列は理にかなっている場合にのみ。このように、行列の乗算は可換ではありません。3×4行列とする、Bは4×5の行列であり、B、A・Bを乗算する3×5の行列であり、B・A単にできない動作。
行列の乗算は、連想です。
[実施例1]行列乗算。
行列と入力行列データb、新しい行列C = * bの出力。
例えば、サンプル入力
4 3
1 2 3
4 5 6
7 8 9
10 11 12である
。3 5
7 9 10 8 11
。4. 5. 6. 7 8
1 2 4 3 5
サンプル出力
18は42である36 24 30である
54 69 84 114 99
90 138 162 186 114
126 159 192 225 258
(1)アイディアをプログラミングします。
行列乗算の定義によれば、計算は3重ループによって完成されます。
(2)ソース。
する#include <stdio.hに>
する#include <string.hの>
構造体マトリックス
{
int型のマット[110] [110]。//存储矩阵中各元素
INT行、COL。//矩阵的大小、行行、列列
}。
マトリックスMATMUL(、マトリックスBをマトリックス)//矩阵*のB
{
行列C。
c.row = a.row。
c.col = b.col。
memset(c.mat、0、はsizeof(c.mat))。
int型I、J、K。
用(i = 0; I <= a.row; iは++)
(; J <b.col、J = 0 J ++)のための
(; K <a.col; K = 0 ++ k)に対する
c.mat [I] [ J] + = a.mat [I] [K] * b.mat [K] [J]。
Cを返します。
}
int型のmain()
{
int型I、J、X、Y。
行列A、B、C;
scanf関数( "%dの%のD"、およびX&Y)。
a.row = X。
a.col = Y。
(; I <X iは++ I = 0)のための
ための(j = 0; J <yであり、j ++)
のscanf( "%d個"、&a.mat [I] [J])。
scanf関数( "%dの%のD"、およびX&Y)。
b.row = X。
b.col = Y。
(; I <X iは++ I = 0)のための
ための(j = 0; J <yであり、j ++)
のscanf( "%d個"、&b.mat [I] [J])。
C = MATMUL(B)
用(i = 0; iはc.rowを<; iは++)
{
ため(J = 0; J <c.col; J ++)
のprintf( "%5D"、c.mat [I] [J])。
printf( "\ n")を。
}
0を返します。
}
実用的なアプリケーションでは、私たちはしばしば、電力行列演算を使用します。
n個の行列乗算は、n番目の電力AまたはA ^ nは行列Aのn乗と呼ばれていると称される
マトリックスは通常、高速累乗のn乗。のが速い累乗のアイデアを見てみましょう。
法律、したがってA ^ 4 = A * A * A * A =(*はA)*(*はA)= A ^ 2 * A ^ 2との結合行列乗算以来。これは、結論付けることができる:nが偶数である場合、A ^ N = A ^(N / 2)* A ^(N / 2)であり; nが奇数で、A ^ N = A ^(N / 2 )* A ^(N / 2)* A(N / 2四捨五入)。このように、我々はすぐに電源行列を求める考えの同様の二分法を使用することができます。
例えば、A ^ 9 = A * A * A * A * A * A * A * A * A(1〜9倍にすることによって)
= *(*はA)*(*はA)*(A * A)*(*はA)
* =(A ^ 2)^ 4
= *((A ^ 2)^ 2)^ 2(Aの正方形、次いで二乗し、次いでAの残りの1つを乗じ、二乗は、4を乗算します)
C = A ^ Kを設定し、Cは、すなわち、恒等行列に初期化行列の要素に加えて、Cは対角、残りの要素全て0です。
c.mat [i]は[I] = 1、C、マット[I] [J] = 0(I!= j)を。
任意のマトリックスは、それ自体でマトリックスです。つまり、1つの当量行列の整数であることができます。次のようにそのため、マトリックス高速アルゴリズムの電力が記載されています。
しばらく(K!= 0)
{
もし(K%2 == 1)のC = Cを*; // C = C *、及びcは行列の乗算を表し、結果は送信C
= *のA;
B = B / 2。
}
理解、C = A ^ 9アナログ手の数を深めます。
K = 9、K!= 0 C = C * A(演算結果C = A)A = A * A(演算結果A = A ^ 2)
K = K / 2、K = 4!= 0〜4%2 == 0 A = A * A(演算結果A = A ^ 4)
K = K / 2、K = 2!= 0 2%2 == 0 A = A * A(演算結果A = A ^ 8)
K = 2/2 K = 1!= 0、1%2 == 1個のC = C * A(演算結果C = A * A ^ 8 = A ^ 9)A = A * A(演算結果A = A ^ 16 )
エンド・K = 1/2のk = 0アルゴリズム。
図から分かるように、手や進数のカウント処理はわずか9 1001は、フィット感を表します。
[実施例2]高速電力行列。
N * nの行列Aを考えると、A ^ kのを見つけます。
入力フォーマット:
1行目、N、K
N + 1は、第二の列に、各列数n、iは、+ 1番目の行及びjはi及び列jマトリクス行の要素の数を表します
出力フォーマット:
全N行、各行数n、i番目の行及びjはマトリクス行j列のi番目の要素の数を表し、それぞれの金型素子10 ^ 5 + 7
(1)アイディアをプログラミングします。
行列を計算に関与するマトリックス電力計算は、n×n個の正方形でなければならないからです。したがって、次の手順は、変数とCOLのランクを表す行のマトリックスを除去する、構造体の定義を簡略化します。
さらに、行列乗算演算は、結果が大きくなる傾向があり、それは一般的に64ビットの整数です。一般的に、一方では、高精度な操作を避けるために、剰余演算処理を継続します。
(2)ソース。
する#include <stdio.hに>
する#include <string.hの>
に#define MODNUM 100007
マトリックス構造体
{
__int64マット[101] [101]; //メモリー行列要素
};
マトリックスMATMUL(行列A、Bマトリックス、N-INT )
{
行列C;
のmemset(c.mat、0、はsizeof(c.matが));
int型I、J、K、
(I = 1; I <= N; I ++)
のための(J = 1; J <= N-; J ++)
(K = 1; K <= N; K ++)
{
c.mat [I] [J] =(c.mat [I] [J] + a.mat [I] [K] * B .MAT [K] [J])%のMODNUM;
}
戻りC;
}
マトリックスquickMatPow(行列A、N-INT、INT b)は// n次の行列迅速電力B
{
行列C。
memset(c.mat、0、はsizeof(c.mat))。
私はint型。
用(i = 1; iが<= N; iは++)
c.mat [i]は[I] = 1。
一方、(B!= 0)
{
IF(B&1)
C = MATMUL(C、N)。// C = C *;
= MATMUL(、N)// A = A *
B / = 2;
}
Cを返します。
}
int型のmain()
{
int型I、J、N、K。
マトリックス;
scanf関数( "%d個の%のD"、&N&K)。
(私は++; iが<= N I = 1)のための
(; J <= N; J ++ J = 1)のため
のscanf( "%I64d"、&a.mat [I] [J])。
= quickMatPow(N、K)。
用(i = 1; iが<= N; iは++)
{
用(J = 1; J <= N; J ++)
のprintf( "%I64d"、a.mat [I] [J])。
printf( "\ n")を。
}
0を返します。
}