2012-10-09 20:15:23Morris
[ZJ] a473. 外援計畫
外援計畫 |
Background
小光上了大學之後,隔了一年考了轉學考,想說到新的學校會不會有比 ACM-ICPC 的隊友存在,但沒想到另一面臨的問題使得小光更加地沮喪。而這個問題,小光無法好好的敘述清楚,原因都是他的語文能力太差,講起話來大多語無倫次,連想為大家出一個好題目都辦不到。
上線性代數小考的時候,沒想到同班同學火速交卷,小光萬萬沒想到同學們算矩陣特別得快速、精準度也十分地好,相較之下,小光即使算出來了,錯誤率極高,總是希望有人可以幫他驗算,但是小光的朋友很少,希望你幫幫他。
The Problem
給定三個 N 階矩陣 A B C,小光利用公式(AB = C)已經算出 C,請驗證C的正確與否。
輸入說明
:
輸入的每一行包含多筆測試。一個測試資料遞一行包含一個整數 N,0 < N ≦ 500。
接下來有 N 行,每行上有 N 個整數 Aij 。
接下來有 N 行,每行上有 N 個整數 Bij 。
接下來有 N 行,每行上有 N 個整數 Cij 。
任何數字一定可以在 long long(64bits) 儲存。
輸出說明
:
輸出 "YES" 或者是 "NO"。
範例輸入 :
2 1 2 3 4 5 7 6 8 17 23 39 53
範例輸出 :
YES
提示
:
出處
:
(管理:morris1028)
擷取至 Matrix67 文章點此
脑海中出现的另一个牛B算法题则是POJ3318: 给你三个n*n的矩阵A、B、C,问你A*B是不是等于C。数据保证O(n^3)铁定超时,因此你需要想一个不用把A和B乘起来就可以验证的算法。一个基 于概率的算法是随机生成一个n乘1的矩阵R,然后判断A*B*R是否等于C*R,而前者相当于A*(B*R),与后者一样都可以在O(n^2)的时间里算 出来。如果算出来的结果相等,几乎可以肯定A*B和C也是相等的。
/**********************************************************************************/
/* Problem: a473 "外援計畫" from */
/* Language: C (1112 Bytes) */
/* Result: AC(312ms, 6.2MB) judge by this@ZeroJudge */
/* Author: morris1028 at 2012-10-08 14:39:11 */
/**********************************************************************************/
#include <stdio.h>
#define FOR(i,n) for(i=0;i<n;i++)
#define LL long long
#define N 505
LL A[N][N], B[N][N], C[N][N], R[N], D[N], E[N];
int n, i, j;
int solve() {
FOR(i,n)
R[i] = i+1, D[i] = E[i] = 0;
FOR(i,n)FOR(j,n)
E[i] += C[i][j]*R[j];
FOR(i,n)FOR(j,n)
D[i] += B[i][j]*R[j];
FOR(i,n) R[i] = 0;
FOR(i,n)FOR(j,n)
R[i] += A[i][j]*D[j];
FOR(i,n)
if(R[i] != E[i])
return 0;
return 1;
}
LL ReadInt(LL *x) {
static char c, neg;
while((c = getchar()) < '-') {if(c == EOF) return EOF;}
neg = (c == '-') ? -1 : 1;
*x = (neg == 1) ? c-'0' : 0;
while((c = getchar()) >= '0')
*x = (*x << 3) + (*x << 1) + c-'0';
*x *= neg;
return 1;
}
int main() {
while(scanf("%d", &n) == 1) {
FOR(i,n)FOR(j,n)
ReadInt(&A[i][j]);
FOR(i,n)FOR(j,n)
ReadInt(&B[i][j]);
FOR(i,n)FOR(j,n)
ReadInt(&C[i][j]);
if(solve())
puts("YES");
else
puts("NO");
}
return 0;
}