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
",C.sum());
68         read(n);    read(k);
69         A.clear();
70         B.clear();
71         tmp.clear();
72         C.clear();
73     }
74     return 0;
75 }
View Code

  用指向一维数组的指针貌似挺耗费内存的,于是改用了二级指针来试下,果然内存和效率都明显有了很大的提高(但好像还是比不上 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
",C.sum());
73         read(n);    read(k);
74         A.clear();
75         B.clear();
76         tmp.clear();
77         C.clear();
78     }
79     return 0;
80 }
View Code

  后来无意中看到别人的代码用 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
",C.sum());
72         read(n);    read(k);
73     }
74     return 0;
75 }
View Code

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

原文地址:https://www.cnblogs.com/Newdawn/p/4390951.html