hdu 4965 Fast Matrix Calculation

  题目链接:hdu 4965,题目大意:给你一个 n*k 的矩阵 A 和一个 k*n 的矩阵 B,定义矩阵 C= A*B,然后矩阵 M= C^(n*n),矩阵中一切元素皆 mod 6,最后求出 M 中所有元素的和。题意很明确了,便赶紧敲了个矩阵快速幂的模板(因为编程的基本功不够还是调试了很久),然后提交后TLE了,改了下细节,加了各种特技,比如输入优化什么的,还是TLE,没办法,只好搜题解,看了别人的题解后才知道原来 A*B 已经是 n*n 的矩阵了,所以(A*B)n*n 的快速幂里的每个乘法都是 n级别的了,n 的上限为1000,这样子超时也不奇怪了,怎么办呢,原来是要转化一下:(A*B)n*n= A*(B*A)n*n-1*A,这样子的话,B*A 是 k*k 的矩阵,乘法是 k级别的,k<=6,就不会超时了,这个转化果然好厉害!

  如果结构体内直接开个数组的话会超内存,要用指向一维数组的指针来 new 才行,不过还是很容易出错:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cctype>
 4 #include<algorithm>
 5 using namespace std;
 6 #define For(i,s,t)  for(int i=s; i<=t; ++i)
 7 const int mod= 6;
 8 const int maxn= 1002;
 9
10 struct matrix{
11     int n,m, (*a)[maxn]= NULL;
12     matrix(int n=1, int m=1):n(n),m(m){
13         a= new int[n+2][maxn];
14         For(i,1,n)    For(j,1,m)
15         a[i][j]= 0;
16     }
17     void identity(){
18         For(i,1,n)    a[i][i]= 1;
19     }
20     matrix operator *(const matrix &m2) const {
21         matrix mul(n,m2.m);
22         For(i,1,n)    For(j,1,m2.m)    For(k,1,m)
23             mul.a[i][j]= (mul.a[i][j]+a[i][k]*m2.a[k][j]%mod)%mod;
24         return mul;
25     }
26     int sum(){
27         int ans= 0;
28         For(i,1,n)    For(j,1,m)
29         ans+= a[i][j];
30         return ans;
31     }
32     void clear()    {    delete[] a;    }
33 };
34
35 matrix quick_mod(matrix m2, int p){
36     matrix ans(m2.n,m2.m);
37     ans.identity();
38     while(p){
39         if(p&1)      ans= ans*m2;
40         m2= m2*m2;
41         p>>=1;
42     }
43     return ans;
44 }
45
46 void read(int &x){
47     x= 0;
48     char ch= getchar();
49     while(!isdigit(ch))        ch= getchar();
50     while(isdigit(ch)){
51         x= x*10+(ch-‘0‘+0);
52         ch= getchar();
53     }
54 }
55
56 int main(){
57     int n,k;
58     read(n);    read(k);
59     while(2){
60         if(!n || !k)    break;
61         matrix A(n,k), B(k,n), tmp(k,k), C(n,n);
62         For(i,1,n)    For(j,1,k)    read(A.a[i][j]);
63         For(i,1,k)    For(j,1,n)    read(B.a[i][j]);
64         tmp= B*A;
65         tmp= quick_mod(tmp,n*n-1);
66         C= A*tmp*B;
67         printf("%d\n",C.sum());
68         read(n);    read(k);
69         A.clear();
70         B.clear();
71         tmp.clear();
72         C.clear();
73     }
74     return 0;
75 }

  用指向一维数组的指针貌似挺耗费内存的,于是改用了二级指针来试下,果然内存和效率都明显有了很大的提高(但好像还是比不上 vector 耶~):

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cctype>
 4 #include<algorithm>
 5 using namespace std;
 6 #define For(i,s,t)  for(int i=s; i<=t; ++i)
 7 const int mod= 6;
 8 const int maxn= 1002;
 9
10 struct matrix{
11     int n,m, **a= NULL;
12     matrix(int n=1, int m=1):n(n),m(m){
13         a= new int *[n+2];
14         For(i,1,n)    a[i]= new int[m+2];
15         For(i,1,n)    For(j,1,m)
16         a[i][j]= 0;
17     }
18     void identity(){
19         For(i,1,n)    a[i][i]= 1;
20     }
21     matrix operator *(const matrix &m2) const {
22         matrix mul(n,m2.m);
23         For(i,1,n)    For(j,1,m2.m)    For(k,1,m)
24             mul.a[i][j]= (mul.a[i][j]+a[i][k]*m2.a[k][j]%mod)%mod;
25         return mul;
26     }
27     int sum(){
28         int ans= 0;
29         For(i,1,n)    For(j,1,m)
30         ans+= a[i][j];
31         return ans;
32     }
33     void clear(){
34         For(i,1,n)    delete a[i];
35         delete a;
36         a = NULL;
37     }
38 };
39
40 matrix quick_mod(matrix m2, int p){
41     matrix ans(m2.n,m2.m);
42     ans.identity();
43     while(p){
44         if(p&1)      ans= ans*m2;
45         m2= m2*m2;
46         p>>=1;
47     }
48     return ans;
49 }
50
51 void read(int &x){
52     x= 0;
53     char ch= getchar();
54     while(!isdigit(ch))        ch= getchar();
55     while(isdigit(ch)){
56         x= x*10+(ch-‘0‘+0);
57         ch= getchar();
58     }
59 }
60
61 int main(){
62     int n,k;
63     read(n);    read(k);
64     while(2){
65         if(!n || !k)    break;
66         matrix A(n,k), B(k,n), tmp(k,k), C(n,n);
67         For(i,1,n)    For(j,1,k)    read(A.a[i][j]);
68         For(i,1,k)    For(j,1,n)    read(B.a[i][j]);
69         tmp= B*A;
70         tmp= quick_mod(tmp,n*n-1);
71         C= A*tmp*B;
72         printf("%d\n",C.sum());
73         read(n);    read(k);
74         A.clear();
75         B.clear();
76         tmp.clear();
77         C.clear();
78     }
79     return 0;
80 }

  后来无意中看到别人的代码用 vector 来代替动态数组就行,不用自己手动 new 和 delete 了,确实方便了好多:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cctype>
 4 #include<vector>
 5 #include<algorithm>
 6 using namespace std;
 7 #define For(i,s,t)  for(int i=s; i<=t; ++i)
 8 const int mod= 6;
 9 const int maxn= 1002;
10
11 struct matrix{
12     int n,m;
13     vector<vector<int> >  a;
14     matrix(int n=1, int m=1):n(n),m(m){
15         a.resize(n+1);
16         For(i,1,n)    a[i].resize(m+1,0);
17     }
18     void identity(){
19         For(i,1,n)    a[i][i]= 1;
20     }
21     matrix operator *(const matrix &m2) const {
22         matrix mul(n,m2.m);
23         For(i,1,n)    For(j,1,m2.m)    For(k,1,m)
24             mul.a[i][j]= (mul.a[i][j]+a[i][k]*m2.a[k][j]%mod)%mod;
25         return mul;
26     }
27     int sum(){
28         int ans= 0;
29         For(i,1,n)    For(j,1,m)
30         ans+= a[i][j];
31         return ans;
32     }
33     ~matrix() {
34         For(i,1,n)    a[i].clear();
35         a.clear();
36     }
37 };
38
39 matrix quick_mod(matrix m2, int p){
40     matrix ans(m2.n,m2.m);
41     ans.identity();
42     while(p){
43         if(p&1)      ans= ans*m2;
44         m2= m2*m2;
45         p>>=1;
46     }
47     return ans;
48 }
49
50 void read(int &x){
51     x= 0;
52     char ch= getchar();
53     while(!isdigit(ch))        ch= getchar();
54     while(isdigit(ch)){
55         x= x*10+(ch-‘0‘+0);
56         ch= getchar();
57     }
58 }
59
60 int main(){
61     int n,k;
62     read(n);    read(k);
63     while(2){
64         if(!n || !k)    break;
65         matrix A(n,k), B(k,n), tmp(k,k), C(n,n);
66         For(i,1,n)    For(j,1,k)    read(A.a[i][j]);
67         For(i,1,k)    For(j,1,n)    read(B.a[i][j]);
68         tmp= B*A;
69         tmp= quick_mod(tmp,n*n-1);
70         C= A*tmp*B;
71         printf("%d\n",C.sum());
72         read(n);    read(k);
73     }
74     return 0;
75 }

  看来自己曾经引以为傲的矩阵快速幂还差得很远啊~~总之得加把劲了!

时间: 2024-10-13 18:28:26

hdu 4965 Fast Matrix Calculation的相关文章

HDU 4965 Fast Matrix Calculation 【矩阵】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4965 题目大意:给你一个N*K的矩阵A以及一个K*N的矩阵B (4 <= N <= 1000)以及 (2 <=K <= 6),然后接下来四步: 算一个新的矩阵C=A*B 算M=C^ (N*N) 对于M中的每个元素%6 将M中每个元素加起来,算出和. 也就是求出A*B * A*B * A*B * A*B * A*B *--* A*B   但是A*B形成的矩阵是N*N,而N大小有可能是10

hdu 4965 Fast Matrix Calculation(矩阵快速幂)

题目链接:hdu 4965 Fast Matrix Calculation 题目大意:给定两个矩阵A,B,分别为N*K和K*N: 矩阵C = A*B 矩阵M=CN?N 将矩阵M中的所有元素取模6,得到新矩阵M' 计算矩阵M'中所有元素的和 解题思路:因为矩阵C为N*N的矩阵,N最大为1000,就算用快速幂也超时,但是因为C = A*B, 所以CN?N=ABAB-AB=AC′N?N?1B,C' = B*A, 为K*K的矩阵,K最大为6,完全可以接受. #include <cstdio> #inc

HDU 4965 Fast Matrix Calculation(矩阵快速幂)

HDU 4965 Fast Matrix Calculation 题目链接 矩阵相乘为AxBxAxB...乘nn次,可以变成Ax(BxAxBxA...)xB,中间乘n n - 1次,这样中间的矩阵一个只有6x6,就可以用矩阵快速幂搞了 代码: #include <cstdio> #include <cstring> const int N = 1005; const int M = 10; int n, m; int A[N][M], B[M][N], C[M][M], CC[N]

HDU 4965 Fast Matrix Calculation(矩阵高速幂)

HDU 4965 Fast Matrix Calculation 题目链接 矩阵相乘为AxBxAxB...乘nn次.能够变成Ax(BxAxBxA...)xB,中间乘n n - 1次,这样中间的矩阵一个仅仅有6x6.就能够用矩阵高速幂搞了 代码: #include <cstdio> #include <cstring> const int N = 1005; const int M = 10; int n, m; int A[N][M], B[M][N], C[M][M], CC[N

hdu 4965 Fast Matrix Calculation(矩阵快速幂)2014多校训练第9场

Fast Matrix Calculation                                                                   Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description One day, Alice and Bob felt bored again, Bob knows Ali

HDU 4965 Fast Matrix Calculation (矩阵快速幂取模----矩阵相乘满足结合律)

http://acm.hdu.edu.cn/showproblem.php?pid=4965 利用相乘的可结合性先算B*A,得到6*6的矩阵,利用矩阵快速幂取模即可水过. 1 #include<iostream> 2 #include<stdio.h> 3 #include<iostream> 4 #include<stdio.h> 5 #define N 1010 6 #define M 1010 7 #define K 6 8 using namespa

HDU 4965 Fast Matrix Calculation(矩阵高速幂)

题目大意:给你两个数字n和k,然后给你两个矩阵a是n*k的和b是k*n的,矩阵c = a*b,让你求c^(n*n). 直接求的话c是n*n的矩阵所以是1000*1000.会超时的啊. 能够转化一下:(a*b)^(n*n)=a*(b*a)^(n*n-1)*b.b*a能够得到一个k*k的矩阵,k非常小所以不会超时.高速幂一下就能够了啊. Fast Matrix Calculation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 13

hdu 4965 Fast Matrix Calculation(矩阵快速幂)

题意: 给你一个N*K的矩阵A和一个K*N的矩阵B,设矩阵C=AB,M=C^(N*N),矩阵Mmod6后,所有数的和是多少 思路: 刚开始我是直接计算的,开了一个1000*1000的矩阵,结果直接爆掉了 后来看了看题解,发现想的很巧妙 观察 M=ABABAB....AB,AB每次都是1000*1000,可是BA确是6*6的 那么 M=A(BABABA..BA)B,我们让BA进行矩阵快速幂就不会爆掉了 M=A(BA)^(N*N-1)B,最后计算一下就好了 代码: #include <iostrea

HDU 4965 Fast Matrix Calculation 矩阵乘法 乘法结合律

一种奇葩的写法,纪念一下当时的RE. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <algorithm> 7 #include <string> 8 #include <queue> 9 #include <stack>