您的位置:首页 > 其它

hpu 1183 线代+hdu 4965 Fast Matrix Calculation【矩阵快速幂+思维】

2017-08-18 09:19 232 查看


1183: 线代 [矩阵]

时间限制: 10 Sec 内存限制:
128 MB


题目描述

学过线性代数后,Ocean又有了新的难题。
现在Ocean有两个矩阵AA和BB,大小分别为n∗xn∗x和x∗mx∗m。现在Ocean想知道新矩阵C=(A∗B)tC=(A∗B)t。
但是输出矩阵太麻烦了,你只需要告诉他CC矩阵元素之和对666666取余的结果即可。
所有测试数据保证nn 等于 mm。请认真读题

C=A∗BC=A∗B程序实现:
假设AA矩阵是n∗xn∗x的,BB矩阵是x∗mx∗m的,则得到的CC矩阵是n∗mn∗m的。
程序实现C=A∗BC=A∗B如下:
int n, x, m;
int A[1001][10], B[10][1001], C[1001][1001];
int i, j, k;
for(i = 0; i < n; i++) {
    for(j = 0; j < m; j++) {
        C[i][j] = 0;
    }
}
for(i = 0; i < n; i++) {
    for(k = 0; k < x; k++) {
        if(A[i][k] == 0) continue;
        for(j = 0; j < m; j++) {
            C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % 666;
        }
    }
}



输入

第一行输入一个整数TT,代表有TT组测试数据。
每组数据占多行,第一行依次输入四个整数n,x,m,tn,x,m,t分别代表上面提到的信息。
接下来有nn行,每行输入xx个元素代表AA矩阵。
后面再有xx行,每行输入mm个元素代表BB矩阵。

注:1<=T<=100,1<=n,m,t<=1000,1<=x<=6,1<=1<=T<=100,1<=n,m,t<=1000,1<=x<=6,1<=矩阵元素 <=66。<=66。


输出

输出一个整数,代表CC矩阵元素之和对666666取余后的结果。


样例输入

2
10 3 10 1000
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
10 4 10 1000
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7


样例输出

396
340

题目链接

思路:
一开始用结构体去存,应该是爆栈了,那只能用数组模拟了。快速幂+矩阵相乘,由于n,m比较大且相等,直接写肯定TLE,本题有个技巧需要用:A * B * A * B * A * B = A *(B * A * B * A)* B,这样就把  n * m的t次方  矩阵化为:n * x * ( x * x 的 t - 1 次方) * x * m,问题就解决了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const int mod = 666;
int T, n, m, x, t;
int A[1010][1010], B[1010][1010], C[1010][1010], D[1010][1010], E[1010][1010];

void mat_mul() {
memset(C, 0, sizeof(C));
for(int i = 0; i < x; i++) {
for(int j = 0; j < n; j++) {
for(int k = 0; k < x; k++) {
C[i][k] = (C[i][k] + B[i][j] * A[j][k]) % mod;
}
}
}
}

int main() {
scanf("%d", &T);
while(T--) {
scanf("%d %d %d %d", &n, &x, &m, &t);
for(int i = 0; i < n; i++)
for(int j = 0; j < x; j++)
scanf("%d", &A[i][j]);
for(int i = 0; i < x; i++)
for(int j = 0; j < m; j++)
scanf("%d", &B[i][j]);
mat_mul();
memset(D, 0, sizeof(D));
for(int i = 0; i <= x; i++) { //初始化单位矩阵
D[i][i] = 1;
}
t--;
while(t) {
if(t & 1) {
memset(E, 0, sizeof(E)); //用一个矩阵做中间值传递
for(int i = 0; i < x; i++) {
for(int j = 0; j < x; j++) {
for(int k = 0; k < x; k++) {
E[i][k] = (E[i][k] + D[i][j] * C[j][k]) % mod;
}
}
}
for(int i = 0; i < x; i++) {
for(int j = 0; j < x; j++ ) {
D[i][j] = E[i][j];
}
}
}
memset(E, 0, sizeof(E));
for(int i = 0; i < x; i++) {
for(int j = 0; j < x; j++) {
for(int k = 0; k < x; k++) {
E[i][k] = (E[i][k] + C[i][j] * C[j][k]) % mod;
}
}
}
for(int i = 0; i < x; i++) {
for(int j = 0; j < x; j++) {
C[i][j] = E[i][j];
}
}
t >>= 1;
}
memset(C, 0, sizeof(C));
for(int i = 0; i < n; i++) {
for(int j = 0; j < x; j++) {
for(int k = 0; k < x; k++) {
C[i][k] = (C[i][k] + A[i][j] * D[j][k]) % mod;
}
}
}
memset(D, 0, sizeof(D));
for(int i = 0; i < n; i++) {
for(int j = 0; j < x; j++) {
for(int k = 0; k < m; k++) {
D[i][k] = (D[i][k] + C[i][j] * B[j][k]) % mod;
}
}
}
int sum = 0;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
sum = (sum + D[i][j]) % mod;
printf("%d\n", sum % mod);
}
return 0;
}

类似这个题目:

HDU 4965

相同的处理方式

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define max_n 1010
const int mod = 6;
using namespace std;
typedef long long LL;
int A[max_n][max_n], B[max_n][max_n], C[max_n][max_n], D[max_n][max_n], E[max_n][max_n];

int main() {
int n, m;
while(scanf("%d %d", &n, &m) && (n + m)) {
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
scanf("%d", &A[i][j]);
}
}
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
scanf("%d", &B[i][j]);
}
}
memset(C, 0, sizeof(C));
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
for(int k = 0; k < m; k++) {
C[i][k] = (C[i][k] + B[i][j] * A[j][k]) % mod;
}
}
}
int t = n * n;
t--;
memset(D, 0, sizeof(D));
for(int i = 0; i < m; i++) {
D[i][i] = 1;
}
while(t) {
if(t & 1) {
memset(E, 0, sizeof(E));
for(int i = 0; i < m; i++) {
for(int j = 0; j < m; j++) {
for(int k = 0; k < m; k++) {
E[i][k] = (E[i][k] + C[i][j] * D[j][k]) % mod;
}
}
}
for(int i = 0; i < m; i++) {
for(int j = 0; j < m; j++) {
D[i][j] = E[i][j];
}
}
}
memset(E, 0, sizeof(E));
for(int i = 0; i < m; i++) {
for(int j = 0; j < m; j++) {
for(int k = 0; k < m; k++) {
E[i][k] = (E[i][k] + C[i][j] * C[j][k]) % mod;
}
}
}
for(int i = 0; i < m; i++) {
for(int j = 0; j < m; j++) {
C[i][j] = E[i][j];
}
}
t >>= 1;
}
memset(E, 0, sizeof(E));
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
for(int k = 0; k < m; k++) {
E[i][k] = (E[i][k] + A[i][j] * D[j][k]) % mod;
}
}
}
memset(D, 0, sizeof(D));
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
for(int k = 0; k < n; k++) {
D[i][k] = (D[i][k] + E[i][j] * B[j][k]) % mod;
}
}
}
int sum = 0;
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
sum += D[i][j];
}
}
printf("%d\n", sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: