Matrix multiplication
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Problem Description
Given two matrices A and B of size n×n, find the product of them.
bobo hates big integers. So you are only asked to find the result modulo 3.
bobo hates big integers. So you are only asked to find the result modulo 3.
Input
The input consists of several tests. For each tests:
The first line contains n (1≤n≤800). Each of the following n lines contain n integers -- the description of the matrix A. The j-th integer in the i-th line equals A ij. The next n lines describe the matrix B in similar format (0≤A ij,B ij≤10 9).
The first line contains n (1≤n≤800). Each of the following n lines contain n integers -- the description of the matrix A. The j-th integer in the i-th line equals A ij. The next n lines describe the matrix B in similar format (0≤A ij,B ij≤10 9).
Output
For each tests:
Print n lines. Each of them contain n integers -- the matrix A×B in similar format.
Print n lines. Each of them contain n integers -- the matrix A×B in similar format.
Sample Input
1 0 1 2 0 1 2 3 4 5 6 7
Sample Output
0 0 1 2 1
题意:给出两个n*n的矩阵,求这两个矩阵的乘积,结果对3取余。
奇妙的题,循环外提巧妙AC
相关博客:http://blog.csdn.net/gogdizzy/article/details/9003369
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 805;
int a[N][N], b[N][N], ans[N][N];
int main()
{
int n, i, j, k;
while(~scanf("%d",&n))
{
for(i = 1; i <= n; i++)
for(j = 1; j <= n; j++)
{
scanf("%d",&a[i][j]);
a[i][j] %= 3;
}
for(i = 1; i <= n; i++)
for(j = 1; j <= n; j++)
{
scanf("%d",&b[i][j]);
b[i][j] %= 3;
}
memset(ans, 0, sizeof(ans));
for(k = 1; k <= n; k++) //经典算法中这层循环在最内层,放最内层会超时,但是放在最外层或者中间都不会超时,不知道为什么
for(i = 1; i <= n; i++)
for(j = 1; j <= n; j++)
{
ans[i][j] += a[i][k] * b[k][j];
//ans[i][j] %= 3; //如果在这里对3取余,就超时了
}
for(i = 1; i <= n; i++)
{
for(j = 1; j < n; j++)
printf("%d ", ans[i][j] % 3);
printf("%d\n", ans[i][n] % 3);
}
}
return 0;
}
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 805;
int a[N][N], b[N][N], ans[N][N];
int main()
{
int n, i, j, k;
while(~scanf("%d",&n))
{
for(i = 1; i <= n; i++)
for(j = 1; j <= n; j++)
{
scanf("%d",&a[i][j]);
a[i][j] %= 3;
}
for(i = 1; i <= n; i++)
for(j = 1; j <= n; j++)
{
scanf("%d",&b[i][j]);
b[i][j] %= 3;
}
memset(ans, 0, sizeof(ans));
for(k = 1; k <= n; k++) //经典算法中这层循环在最内层,放最内层会超时,但是放在最外层或者中间都不会超时,不知道为什么
for(i = 1; i <= n; i++)
for(j = 1; j <= n; j++)
{
ans[i][j] += a[i][k] * b[k][j];
//ans[i][j] %= 3; //如果在这里对3取余,就超时了
}
for(i = 1; i <= n; i++)
{
for(j = 1; j < n; j++)
printf("%d ", ans[i][j] % 3);
printf("%d\n", ans[i][n] % 3);
}
}
return 0;
}
另外:
解题思路:如果按照先求矩阵C 再求C的(N*N)肯定会超时,因为C有N行N列,最多为1000*1000*1000*log2(1000000)。但是我们可以用到一个矩阵的性质。矩阵虽然不满足交换律但是他满足结合律。这边C是A和B的矩阵乘积。C的N*N次方相当于(A*B)^(N*N) = A*B*A*B...*A*B 总共N*N个。即 原式 = A * (B*A)*(B*A)...(B*A)*B 总共有N*N-1个的B*A。然后我们就可以根据B*A来算了。这边K最多是6 所以算中间这一部分的值为6*6*6*log2(1000000-1).这样,我们使用矩阵快速幂,就不会超时了。
由于结构体里开不了1000*1000的大小,所以只开了6*6的矩阵。剩下的用普通的矩阵乘法计算。
#include <iostream>#include <queue>
#include <stack>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cstdio>
using namespace std;
struct matrix
{
int ma[15][15];
int row,col;
};
matrix operator *(matrix a,matrix b)
{
matrix w;
memset(w.ma,0,sizeof(w.ma));
for (int i=0; i<a.row; i++)
for (int j=0; j<b.col; j++)
for (int h=0; h<a.col; h++)
w.ma[i][j]=(w.ma[i][j]+a.ma[i][h]*b.ma[h][j])%6;
w.row=a.row;
w.col=b.col;
return w;
}
matrix operator ^(matrix a,__int64 b)
{
matrix w;
for (int i=0; i<6; i++) for (int j=0; j<6; j++) w.ma[i][j]=(i==j);
w.row=6;
w.col=6;
while (b)
{
if (b&1) w=w*a;
a=a*a;
b>>=1;
}
return w;
}
int ans1[1111][1111];
int ans[1111][15];
int a[1111][15],b[15][1111];
matrix va;
int main()
{
__int64 n,k,i,j;
while (~scanf(" %I64d %I64d",&n,&k),(n|k))
{
for (i=0; i<n; i++)
for (j=0; j<k; j++) scanf(" %d",&a[i][j]);
for (i=0; i<k; i++)
for (j=0; j<n; j++) scanf(" %d",&b[i][j]);
for (int i=0; i<k; i++)
for (int j=0; j<k; j++)
{
va.ma[i][j]=0;
for (int h=0; h<n; h++)
va.ma[i][j]=(va.ma[i][j]+b[i][h]*a[h][j])%6;
}
va.row=k;
va.col=k;
__int64 m=n*n;
va=va^(m-1);
for (int i=0; i<n; i++)
for (int j=0; j<k; j++)
{
ans[i][j]=0;
for (int h=0; h<k; h++)
ans[i][j]=(ans[i][j]+a[i][h]*va.ma[h][j])%6;
}
for (int i=0; i<n; i++)
for (int j=0; j<n; j++)
{
ans1[i][j]=0;
for (int h=0; h<k; h++)
ans1[i][j]=(ans1[i][j]+ans[i][h]*b[h][j])%6;
}
__int64 sum=0;
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
sum+=(ans1[i][j]%6);
}
}
printf("%I64d\n",sum);
}
return 0;
}