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 }
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\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 }
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\n",C.sum());

72         read(n);    read(k);

73     }

74     return 0;

75 }
View Code

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

你可能感兴趣的:(Matrix)