zoukankan      html  css  js  c++  java
  • 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

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

  • 相关阅读:
    输入和输出

    4. 深入 Python 流程控制
    js下拉框选择图片
    按下enter触发事件
    js多种方法取数组的最后一个元素
    apply,call,bind函数作用与用法
    vue中的js绑定样式
    js添加删除class
    rem等比例自适应手机尺寸
  • 原文地址:https://www.cnblogs.com/Newdawn/p/4390951.html
Copyright © 2011-2022 走看看