题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4920
题意很简单,就是输出两个矩阵相乘的结果,但是时间要求比较高。
现在我们来回顾一下原始的矩阵写法:
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
for(int k=0; k<n; k++){
c[i][j] = c[i][j] + a[i][k] + a[k][j];
}
}
}
原始写法可以理解为,站在答案矩阵c的角度上的写法。
那么,如果站在矩阵a或者b的角度上呢?如果a矩阵某个a[i][j]为0,就可以不进行乘法运算,那么修改一下,就可以在a[i][j]为0的时候省去一重循环,这将是很大的优化!!!
写法:
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
if(a[i][j]==0) continue;
for(int k=0; k<n; k++)
c[i][k] += a[i][j] * b[j][k];
}
}
顺便说说c矩阵清空的问题,用for循环会比memset 快(个人感觉)。
此外,此题应该输入时取一次模(这将导致a, b举证中可能出现大量0元素), 输出时取一次模,而非边加边模(模导致大量时间开销)
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
LL a[810][810], b[810][810], c[810][810];
void Input(LL (*kw)[810], int n){
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
scanf("%lld", &kw[i][j]), kw[i][j]%=3;
return ;
}
void Output(int n){
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
c[i][j] = 0;
for(int i=0; i<n; i++)
for(int j=0; j<n; j++){
if(a[i][j]==0) continue;
for(int k=0; k<n; k++)
c[i][k]=c[i][k]+a[i][j]*b[j][k];
}
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
if(j) printf(" ");
printf("%lld", c[i][j]%3);
}
printf("\n");
}
return;
}
int main(){
int n;
while(~scanf("%d", &n)){
Input(a, n);
Input(b, n);
Output(n);
}
return 0;
}