zoukankan      html  css  js  c++  java
  • 矩阵总结 ACM

    先介绍一篇矩阵好的博文 Matrix 67:http://www.matrix67.com/blog/archives/276

     

    一.高斯消元

    我觉得不错的模板

     

    // 高斯消元法解方程组(Gauss-Jordan elimination).(-2表示有浮点数解,但无整数解,
    //-1表示无解,0表示唯一解,大于0表示无穷解,并返回自由变元的个数)
    //有equ个方程,var个变元。增广矩阵行数为equ,分别为0到equ-1,列数为var+1,分别为0到var.
    int Gauss(int equ,int var){
        int i,j,k;
        int max_r;// 当前这列绝对值最大的行.
        int col;//当前处理的列
        int ta,tb;
        int LCM;
        int temp;
        int free_x_num;
        int free_index;
    
        for(int i=0;i<=var;i++){
            x[i]=0;
            free_x[i]=true;
        }
    
        //转换为阶梯阵.
        col=0; // 当前处理的列
        for(k = 0;k < equ && col < var;k++,col++){// 枚举当前处理的行.
    // 找到该col列元素绝对值最大的那行与第k行交换.(为了在除法时减小误差)
            max_r=k;
            for(i=k+1;i<equ;i++)
                if(abs(a[i][col])>abs(a[max_r][col])) 
    				max_r=i;
            if(max_r!=k)// 与第k行交换
                for(j=k;j<var+1;j++) 
    				swap(a[k][j],a[max_r][j]);
            if(a[k][col]==0){// 说明该col列第k行以下全是0了,则处理当前行的下一列.
                k--;
                continue;
            }
            for(i=k+1;i<equ;i++){// 枚举要删去的行.
                if(a[i][col]!=0){
                    LCM = lcm(abs(a[i][col]),abs(a[k][col]));
                    ta = LCM/abs(a[i][col]);
                    tb = LCM/abs(a[k][col]);
                    if(a[i][col]*a[k][col]<0)tb=-tb;//异号的情况是相加
                    for(j=col;j<var+1;j++)
                        a[i][j] = a[i][j]*ta-a[k][j]*tb;
                }
            }
        }
    
        // 1. 无解的情况: 化简的增广阵中存在(0, 0, ..., a)这样的行(a != 0).
    	 // 对于无穷解来说,如果要判断哪些是自由变元,那么初等行变换中的交换就会影响,则要记录交换.
        for (i = k; i < equ; i++)
            if (a[i][col] != 0) return -1;
        // 2. 无穷解的情况: 在var * (var + 1)的增广阵中出现(0, 0, ..., 0)这样的行,即说明没有形成严格的上三角阵.
        // 且出现的行数即为自由变元的个数.
        if (k < var){
            // 首先,自由变元有var - k个,即不确定的变元至少有var - k个.
            for (i = k - 1; i >= 0; i--){
                // 第i行一定不会是(0, 0, ..., 0)的情况,因为这样的行是在第k行到第equ行.
                // 同样,第i行一定不会是(0, 0, ..., a), a != 0的情况,这样的无解的.
                free_x_num = 0; // 用于判断该行中的不确定的变元的个数,如果超过1个,则无法求解,它们仍然为不确定的变元.
                for (j = 0; j < var; j++)
                    if (a[i][j] != 0 && free_x[j]) 
    					free_x_num++, free_index = j;
                if (free_x_num > 1) continue; // 无法求解出确定的变元.
                // 说明就只有一个不确定的变元free_index,那么可以求解出该变元,且该变元是确定的.
                temp = a[i][var];
                for (j = 0; j < var; j++)
                    if (a[i][j] != 0 && j != free_index) 
    					temp -= a[i][j] * x[j];
                x[free_index] = temp / a[i][free_index]; // 求出该变元.
                free_x[free_index] = 0; // 该变元是确定的.
            }
            return var - k; // 自由变元有var - k个.
        }
        // 3. 唯一解的情况: 在var * (var + 1)的增广阵中形成严格的上三角阵.
        // 计算出Xn-1, Xn-2 ... X0.
        for (i = var - 1; i >= 0; i--){
            temp = a[i][var];
            for (j = i + 1; j < var; j++)
                if (a[i][j] != 0) 
    				temp -= a[i][j] * x[j];
            if (temp % a[i][i] != 0) return -2; // 说明有浮点数解,但无整数解.
            x[i] = temp / a[i][i];
        }
        return 0;
    }
    

     

      

     

    1.POJ 1222 EXTENDED LIGHTS OUT

    题目:关灯问题,按下开关,该灯和相邻的灯都会变化灯的状态。现在给出初始状态,问如何设置开关,使得灯的最终状态全为关闭的。。

    分析:我们发现对于i灯,必有ai ^ xi ^ (A) = 0,相当于xi ^ (A) = ai

          A为相邻的几个变量xj ^ xk ^ xl & xm(假设有四个)

          所以我们可以列出30个方程组出来。然后解方程组就行了

    #include <set>
    #include <map>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    #define rep(i,n) for(int i=0;i<n;i++)
    #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
    #define pb push_back
    
    const int X = 35;
    const int n = 30;
    
    int a[X][X];
    
    int dirx[4] = {-1,0,0,1};
    int diry[4] = {0,-1,1,0};
    
    void build(){
        rep(i,5){
            rep(j,6){
                int x = i*6+j;
                a[x][x] = 1;
                rep(k,4){
                    int dx = dirx[k]+i;
                    int dy = diry[k]+j;
                    if(dx>=0&&dx<5 && dy>=0&&dy<6){
                        int y = dx*6+dy;
                        a[x][y] = 1;
                    }
                }
            }
        }
    }
    
    void debug(){
        rep(i,30){
            rep(j,31)
                cout<<a[i][j]<<" ";
            cout<<endl;
        }
    }
    
    void gauss(){
        int i = 0,j = 0;
        while(i<n&&j<n){
            int r = i;
            for(int k=i;k<n;k++)
                if(a[k][j]){
                    r = k;
                    break;
                }
            if(a[r][j]){
                if(r!=i)
                    rep(k,n+1)
                        swap(a[r][k],a[i][k]);
                for(int u=i+1;u<n;u++)
                    if(a[u][j])
                        for(int k=j;k<n+1;k++)
                            a[u][k] ^= a[i][k];
                i ++;
            }
            j ++;
        }
    
        for(int i=n-2;i>=0;i--)
            for(int j=n-1;j>i;j--)
                a[i][n] ^= (a[i][j]&&a[j][n]);
    }
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("sum.in","r",stdin);
    #endif
    
        int ncase;
        cin>>ncase;
        rep(cnt,ncase){
            printf("PUZZLE #%d\n",cnt+1);
            memset(a,0,sizeof(a));
            rep(i,n)
                scanf("%d",&a[i][n]);
            build();
            gauss();
            rep(i,5){
                printf("%d",a[i*6][30]);
                for(int j=1;j<6;j++)
                    printf(" %d",a[i*6+j][30]);
                puts("");
            }
        }
    	return 0;
    }
    

      

    相似的几题

    POJ 1681 Painter's Problem

    #include <set>
    #include <map>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    #define rep(i,n) for(int i=0;i<n;i++)
    #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
    #define pb push_back
    
    const int X = 230;
    
    int n,m;
    int dirx[] = {0,0,-1,1};
    int diry[] = {-1,1,0,0};
    int a[X][X];
    
    void debug(){
        rep(i,n){
            rep(j,n+1)
                cout<<a[i][j]<<" ";
            cout<<endl;
        }
    }
    
    void build(){
        rep(i,m){
            rep(j,m){
                int x = i*m+j;
                a[x][x] = 1;
                rep(k,4){
                    int dx = dirx[k]+i;
                    int dy = diry[k]+j;
                    if(dx>=0&&dx<m && dy>=0&&dy<m){
                        int y = dx*m+dy;
                        a[x][y] = 1;
                    }
                }
            }
        }
    }
    
    int gauss(){
        int i = 0,j = 0;
        while(i<n&&j<n){
            int r = i;
            for(int k=i;k<n;k++)
                if(a[k][j]){
                    r = k;
                    break;
                }
            if(a[r][j]){
                if(r!=i)
                    rep(k,n+1)
                        swap(a[r][k],a[i][k]);
                for(int u=i+1;u<n;u++)
                    if(a[u][j])
                        for(int k=j;k<n+1;k++)
                            a[u][k] ^= a[i][k];
                i ++;
            }
            j ++;
        }
    
        //cout<<"dsaaaaaa "<<i<<endl;
        for(;i<n;i++)
            if(a[i][n])
                return -1;
    
        for(int i=n-2;i>=0;i--)
            for(int j=n-1;j>i;j--)
                a[i][n] ^= (a[i][j]&&a[j][n]);
    
        int cnt = 0;
        for(int i=0;i<n;i++)
            cnt += a[i][n];
        return cnt;
    }
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("sum.in","r",stdin);
    #endif
    
        int ncase;
        cin>>ncase;
        while(ncase--){
            memset(a,0,sizeof(a));
            cin>>m;
            char s[16];
            n = m*m;
            rep(i,m){
                scanf("%s",s);
                rep(j,m)
                    a[i*m+j][n] = (s[j]=='w');
            }
            build();
            int ans = gauss();
            if(ans==-1)
                puts("inf");
            else
                printf("%d\n",ans);
        }
    	return 0;
    }
    

     

    POJ 1830 开关问题

    /*
    
    题目:
        同关灯问题,高斯消元
    
    */
    #include <set>
    #include <map>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    #define rep(i,n) for(int i=0;i<n;i++)
    #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
    #define pb push_back
    
    const int X = 32;
    
    int n;
    int dirx[] = {0,0,-1,1};
    int diry[] = {-1,1,0,0};
    int a[X][X];
    
    void debug(){
        rep(i,n){
            rep(j,n+1)
                cout<<a[i][j]<<" ";
            cout<<endl;
        }
    }
    
    int gauss(){
        int i = 0,j = 0;
        while(i<n&&j<n){
            int r = i;
            for(int k=i;k<n;k++)
                if(a[k][j]){
                    r = k;
                    break;
                }
            if(a[r][j]){
                if(r!=i)
                    rep(k,n+1)
                        swap(a[r][k],a[i][k]);
                for(int u=i+1;u<n;u++)
                    if(a[u][j])
                        for(int k=j;k<n+1;k++)
                            a[u][k] ^= a[i][k];
                i ++;
            }
            j ++;
        }
    
        int cnt = n-i;
        for(;i<n;i++)
            if(a[i][n])
                return -1;
        return 1<<cnt;
    }
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("sum.in","r",stdin);
    #endif
    
        int ncase;
        cin>>ncase;
        while(ncase--){
            cin>>n;
            memset(a,0,sizeof(a));
            int x[X],y;
            rep(i,n)
                scanf("%d",&x[i]);
            rep(i,n){
                scanf("%d",&y);
                a[i][n] = x[i] ^ y;
                a[i][i] = 1;
            }
            int p,q;
            while(scanf("%d%d",&p,&q),p||q)
                a[--q][--p] = 1;
    
            int ans = gauss();
            if(ans==-1)
                puts("Oh,it's impossible~!!");
            else
                printf("%d\n",ans);
        }
    	return 0;
    }
    

     

    URAL 1042 Central Heating

    /*
    
    题目:
        同关灯问题,高斯消元
    
    */
    #include <set>
    #include <map>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    #define rep(i,n) for(int i=0;i<n;i++)
    #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
    #define pb push_back
    
    const int X = 300;
    
    int n;
    int a[X][X];
    
    void debug(){
        rep(i,n){
            rep(j,n+1)
                cout<<a[i][j]<<" ";
            cout<<endl;
        }
    }
    
    int gauss(){
        int i = 0,j = 0;
        while(i<n&&j<n){
            int r = i;
            for(int k=i;k<n;k++)
                if(a[k][j]){
                    r = k;
                    break;
                }
            if(a[r][j]){
                if(r!=i)
                    rep(k,n+1)
                        swap(a[r][k],a[i][k]);
                for(int u=i+1;u<n;u++)
                    if(a[u][j])
                        for(int k=j;k<n+1;k++)
                            a[u][k] ^= a[i][k];
                i ++;
            }
            j ++;
        }
    
        //cout<<"dsaaaaaa "<<i<<endl;
        for(;i<n;i++)
            if(a[i][n])
                return -1;
    
        for(int i=n-2;i>=0;i--)
            for(int j=n-1;j>i;j--)
                a[i][n] ^= (a[i][j]&&a[j][n]);
    
        int cnt = 0;
        for(int i=0;i<n;i++)
            cnt += a[i][n];
        return cnt;
    }
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("sum.in","r",stdin);
    #endif
    
        while(cin>>n){
            memset(a,0,sizeof(a));
    
            rep(i,n){
                int y;
                a[i][n] = 1;
                while(scanf("%d",&y),y!=-1)
                    a[--y][i] = 1;
            }
    
            int ans = gauss();
            if(ans==-1)
                puts("No solution");
            else{
                bool ok = false;
                rep(i,n)
                    if(a[i][n]){
                        ok?putchar(' '):ok = true;
                        printf("%d",i+1);
                    }
                puts("");
            }
        }
    	return 0;
    }
    

     

      

    2.BZOJ 1013 [JSOI2008]球形空间产生器sphere

    题目:中文题。。

    分析:裸的高斯消元题

     二维平面上的圆上的点与圆心的距离有(x-a)^2+(y-b)^2 = r^2

     三维空间上的球上的点与球心的距离有(x-a)^2+(y-b)^2+(z-c)^2 = r^2

     同理:在n维空间上的球上的点与球心的距离有sigma((xi-ai)^2) = r^2,圆心为(a1,a2,...,an)

     另外,在二维平面上,可由三点(不共线)确定一个园,在三维上四点(不共线)确定一个球,同理,在n维平面上,可由n+1个点(不共线)确定一个n维的球。

     这样,题目就可以转化为n+1个方程组,但是是平方级别的,如何转化为一维的?

     我们不妨对于相邻的两个方程组左右分别相减,可以发现:

     2*(x21 - x11)*x1 + 2*(x22 - x12)*x2 +...+2*(x2n - x1n) = (x21^2 - x11^1)+...+(x2n^2 - x1n^2)

     这样,由n+1个方程组就可以转化为了n个一维的方程组了。下面,直接用高斯消元法即 可解决该问题

     

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    
    using namespace std;
    
    const int X = 20;
    #define esp 1e-8
    
    double dp[X][X];
    double a[X][X],b[X][X];
    double f[X];
    int n;
    
    double gauss(){
    	for(int i=1;i<=n;i++){
    		int x = i;
    		for(int j=i+1;j<=n;j++)
    			if(fabs(a[j][i]-a[x][i])>esp)
    				x = j;
    		if(x!=i)
    			for(int j=1;j<=n+1;j++)
    				swap(a[i][j],a[x][j]);
    		for(int j=i+1;j<=n;j++)
    			if(fabs(a[j][i])>esp){
    				double temp = a[j][i] / a[i][i];
    				for(int k=i;k<=n+1;k++)
    					a[j][k] -= temp*a[i][k];
    			}
    	}
    	for(int i=n;i;i--){
    		double temp = a[i][n+1];
    		for(int j=i+1;j<=n;j++)
    			temp -= f[j]*a[i][j];
    		f[i] = temp / a[i][i];
    	}
    }
    
    int main(){
    	cin>>n;
    	for(int i=1;i<n+2;i++)
    		for(int j=1;j<=n;j++)
    			scanf("%lf",&b[i][j]);
    	for(int i=1;i<=n;i++){
    		double temp = 0;
    		for(int j=1;j<=n;j++){
    			temp += b[i+1][j]*b[i+1][j]-b[i][j]*b[i][j];
    			a[i][j] = 2*(b[i+1][j]-b[i][j]);
    		}
    		a[i][n+1] = temp;
    	}
    	gauss();
    	for(int i=1;i<n;i++)
    		printf("%.3lf ",f[i]);
    	printf("%.3lf\n",f[n]);
    	return 0;
    }
    

     

    二.矩阵快速幂

    1.poj 3070 Fibonacci

    题目:求斐波那契数列第n项的后四位数

    分析:由于n很大,我们可以构造矩阵A,B

    A = 1 1     B = f1

        1 0         f0

    则 A^(n-1) * B = fn

                     fn-1

    所以我们可以直接利用矩阵快速幂来求fn%10000

    /*
    
    题目:
        斐波那契数列的矩阵算法
    
    分析:
        裸的矩阵快速幂
    
    */
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    
    const int X = 5;
    const int mod = 10000;
    
    int n;
    
    class matrix{
        public:
            int a[X][X];
            int size;
            int mod;
    
            matrix(){
                memset(a,0,sizeof(a));
            }
            matrix(int _size,int _mod):size(_size),mod(_mod){
                memset(a,0,sizeof(a));
            }
    
            void setE(){
                for(int i=0;i<size;i++)
                    a[i][i] = 1;
            }
    
            matrix operator * (matrix p){
                matrix c(size,mod);
                for(int i=0;i<size;i++)
                    for(int j=0;j<size;j++)
                        for(int k=0;k<size;k++){
                            c.a[i][j] += a[i][k]*p.a[k][j];
                            c.a[i][j] %= mod;
                        }
                return c;
            }
    
            matrix pow(int exp){
                matrix cur = *this;
                matrix c(size,mod);
                c.setE();
    
                while(exp){
                    if(exp&1)
                        c = c*cur;
                    cur = cur*cur;
                    exp = exp>>1;
                }
                return c;
            }
    
            void display(){
                for(int i=0;i<size;i++){
                    for(int j=0;j<size;j++)
                        cout<<a[i][j]<<" ";
                    cout<<endl;
                }
            }
    };
    
    int main(){
        freopen("sum.in","r",stdin);
        while(scanf("%d",&n),n!=-1){
            if(!n){
                puts("0");
                continue;
            }
            matrix ans(2,mod);
            ans.a[0][0] = ans.a[0][1] = ans.a[1][0] = 1;
            ans.a[1][1] = 0;
    
            ans = ans.pow(n-1);
    
            printf("%d\n",ans.a[0][0]);
        }
        return 0;
    }
    

     

    相似的题目:

    hdu 1005 number sequence

     

    /*
    
    题目:
        f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.
        给出A,B求f(n)模7
    
    分析:
        我们可以构造一个矩阵
        [ a b ]  *  [ fn-1 ]  =  [ fn   ]
        [ 1 0 ]     [ fn-2 ]     [ fn-1 ]
    
        最后发现最要求左边的矩阵的(n-2)次幂后所得的上面两项的和值就是
        fn,所以用到了矩阵的快速幂可以做~~
    
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int X = 3;
    
    class matrix{
        public:
            int a[X][X];
    
            matrix(){
                memset(a,0,sizeof(a));
            }
    
            matrix(int _size,int _mod):size(_size),mod(_mod){
                memset(a,0,sizeof(a));
            }
    
            matrix operator * (matrix p){
                matrix c(size,mod);
                for(int i=0;i<size;i++)
                    for(int j=0;j<size;j++)
                        for(int k=0;k<size;k++){
                            c.a[i][j] += a[i][k]*p.a[k][j];
                            c.a[i][j] %= mod;
                        }
                return c;
            }
    
            void setE(){
                for(int i=0;i<size;i++)
                    a[i][i] = 1;
            }
    
             matrix pow(int exp){
                matrix temp(size,mod);
                temp.setE();
                matrix cur = *this;
                while(exp){
                    if(exp&1)
                        temp = temp*cur;
                    cur = cur*cur;
                    exp = exp>>1;
                }
                return temp;
            }
    
        private:
            int size;
            int mod;
    };
    
    int main(){
        freopen("sum.in","r",stdin);
        int a,b,n;
        while(cin>>a>>b>>n,a||b||n){
            if(n==1){
                cout<<1<<endl;
                continue;
            }
            else if(n==2){
                cout<<1<<endl;
                continue;
            }
            matrix ans(2,7);
            ans.a[0][0] = a;
            ans.a[0][1] = b;
            ans.a[1][0] = 1;
            ans.a[1][1] = 0;
    
            ans = ans.pow(n-2);
    
            cout<<(ans.a[0][0]+ans.a[0][1])%7<<endl;
        }
        return 0;
    }
    

     

      

     

     

    2.HOJ 1991 Happy 2005

    题目:
    给出n,问2005^n的各个因子数之和对29取模

    分析:
    2005 = 5*401,我们可以对于401进行分类:
    401^0 : 1 5 5^2 ... 5^n
    401^1 : 401 401*5 401*5^2 ... 401*5^n
    .
    .
    .
    401^n : 401^n 401^n*5 401^n*5^2 ... 401^n*5^n
    由此我们可以发现,问题可以转换为
    (1+401+401^2+...401^n)*(1+5+5^2+...+5^n)%29

    方法一:
    二分再二分。首先,a^n用一次二分,求和的时候再用一次二分。
    a^n二分的时候就是快速幂。
    求和二分:
    A+A^2+A...+A^(2k+1)= A+A^2+...+A^k+A^(k+1)+A^(k+1)*(A+A^2+...+A^k).
    A+A^2+...+A^2k = A+A^2+...+A^k+A^k*(A+A^2+...+A^k).
    方法二:
    构造矩阵matrix如下:
    A 1
    0 1
    我们发现matrix^(n+1)项的时候,第一行第二列就是问题所求
    所以在求A+A^2+A^3+...+A^k % 29的时候,我们可以直接转化为对矩阵进行
    快速幂取模。
    我下面的代码为构造矩阵求解。。。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    
    typedef long long ll;
    
    #define debug puts("here");
    
    const int X = 3;
    const int MOD = 29;
    
    struct Matrix{
    
        ll a[X][X];
        int n;
        int mod;
    
        Matrix(){}
        Matrix(int _n,int _mod):n(_n),mod(_mod){
            memset(a,0,sizeof(a));
        }
    
        void setE(){
            memset(a,0,sizeof(a));
            for(int i=1;i<=n;i++)
                a[i][i] = 1;
        }
    
        Matrix operator * (Matrix p){
            Matrix c(n,mod);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    for(int k=1;k<=n;k++){
                        c.a[i][j] += a[i][k]*p.a[k][j];
                        c.a[i][j] %= mod;
                    }
            return c;
        }
    
        Matrix pw(int exp){
            Matrix cur = *this;
            Matrix c(n,MOD);
            c.setE();
            while(exp>0){
                if(exp&1)
                    c = c*cur;
                cur = cur*cur;
                exp = exp>>1;
            }
            return c;
        }
    
        void di(){
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++)
                    cout<<a[i][j]<<" ";
                cout<<endl;
            }
        }
    
        void init(int x){
            a[1][2] = a[2][2] = 1;
            a[2][1] = 0;
            a[1][1] = x;
        }
    }matrix;
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("sum.in","r",stdin);
    #endif
    
        ll n;
        while(cin>>n,n){
            Matrix a = Matrix(2,MOD);
            a.init(5);
            a = a.pw(n+1);
            ll ans = a.a[1][2]%MOD;
    
            a.init(401);
            a = a.pw(n+1);
            ans = ans*a.a[1][2]%MOD;
            cout<<ans<<endl;
        }
    	return 0;
    }
    

    相似的题目:

    hoj 2635 Weights

    /*
    
    题目:
        直接求1+3^1+...+3^n的和
    
    分析:
            构造矩阵matrix如下:
            A  1
            0  1
            我们发现matrix^(n+1)项的时候,第一行第二列就是问题所求
            所以在求A+A^2+A^3+...+A^k % p的时候,我们可以直接转化为对矩阵进行
            快速幂取模。
        我下面的代码为构造矩阵求解。。。
    
    */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    
    typedef long long ll;
    
    #define debug puts("here");
    
    const int X = 3;
    const int MOD = 9999997;
    
    struct Matrix{
    
        ll a[X][X];
        int n;
        int mod;
    
        Matrix(){}
        Matrix(int _n,int _mod):n(_n),mod(_mod){
            memset(a,0,sizeof(a));
        }
    
        void setE(){
            memset(a,0,sizeof(a));
            for(int i=1;i<=n;i++)
                a[i][i] = 1;
        }
    
        Matrix operator * (Matrix p){
            Matrix c(n,mod);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    for(int k=1;k<=n;k++){
                        c.a[i][j] += a[i][k]*p.a[k][j];
                        c.a[i][j] %= mod;
                    }
            return c;
        }
    
        Matrix pw(int exp){
            Matrix cur = *this;
            Matrix c(n,MOD);
            c.setE();
            while(exp>0){
                if(exp&1)
                    c = c*cur;
                cur = cur*cur;
                exp = exp>>1;
            }
            return c;
        }
    
        void di(){
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++)
                    cout<<a[i][j]<<" ";
                cout<<endl;
            }
        }
    
        void init(int x){
            a[1][2] = a[2][2] = 1;
            a[2][1] = 0;
            a[1][1] = x;
        }
    }matrix;
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("sum.in","r",stdin);
    #endif
    
        ll n;
        while(cin>>n){
            Matrix a = Matrix(2,MOD);
            a.init(3);
            a = a.pw(n);
            //a.di();
            ll ans = a.a[1][2]%MOD;
            cout<<ans<<endl;
        }
    	return 0;
    }
    

    poj 3233 Matrix Power Series

    /*
    
    题目:
        求出 S = A + A^2 + A^3 + … + A^k.
    
    分析:
        解法一
        Let B=   A I
                 0 I
    
        B^(k+1) =    A^k   I+A+...+A^k
                     0          I
    
        解法二
        设f[n]=A^1+A^2+....A^n;
        当n是偶数,f[n]=f[n/2]+f[n/2]*A^(n/2);
        但n是奇数,f[n]=f[n-1]+A^(n);
    
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int X = 31<<2;
    
    int n,m,k;
    
    class matrix{
        public:
            int size;
            int mod;
            int a[X][X];
    
            matrix(){
                memset(a,0,sizeof(a));
            }
    
            matrix(int _size,int _mod):size(_size),mod(_mod){
                memset(a,0,sizeof(a));
            }
    
            void setE(){
                for(int i=0;i<2*size;i++)
                    a[i][i] = 1;
            }
    
            void print(){
                for(int i=0;i<size;i++){
                    printf("%d",a[i][size]);
                    for(int j=1;j<size;j++)
                        printf(" %d",a[i][j+size]);
                    puts("");
                }
            }
    
            matrix operator * (matrix p){
                matrix c(size,mod);
                for(int i=0;i<2*size;i++)
                    for(int j=0;j<2*size;j++)
                        for(int k=0;k<2*size;k++){
                            c.a[i][j] += a[i][k]*p.a[k][j];
                            c.a[i][j] %= mod;
                        }
                return c;
            }
    
            void operator -- (){
                for(int i=0;i<size;i++)
                    a[i][i+size] = (--a[i][i+size]+mod)%mod;
            }
    
            matrix pow(int exp){
                matrix temp(size,mod);
                temp.setE();
                matrix cur = *this;
                while(exp){
                    if(exp&1)
                        temp = temp*cur;
                    cur = cur*cur;
                    exp = exp>>1;
                }
                return temp;
            }
    
            void display(){
                for(int i=0;i<2*size;i++){
                    for(int j=0;j<2*size;j++)
                        cout<<a[i][j]<<" ";
                    cout<<endl;
                }
            }
    };
    
    int main(){
        freopen("sum.in","r",stdin);
        while(cin>>n>>k>>m){
            matrix ans(n,m);
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                    scanf("%d",&ans.a[i][j]);
            for(int i=n;i<2*n;i++)
                ans.a[i-n][i] = ans.a[i][i] = 1;
    
            ans = ans.pow(k+1);
            --ans;
            ans.print();
        }
        return 0;
    }
    

      

    3.线性递推

    对于线性递推f[k] = a*f[k-1]+b*f[k-2]+c*f[k-3]...z*f[0]

    我们可以构造矩阵A,B:

    A = 0 1 0...          B = f[k-1]

          0 0 1...                 f[k-2]

          ..........                  ........

          a b c...                  f[0]

    我们可以发现

    A*B =  f[k]

               f[k-1]

               ........

               f[1]

    所以A^(n-k) * B = f[n]

                                f[n-1]

               ....

              f[n-k+1]

    HOJ 1790 Firepersons

    题目:
    线性递推关系,an=Σ1<=i<=k*an-i*bi,问ai

    分析:
    可以构造矩阵A如下
    0 1 0 ...0
    0 0 1 ...0
    ...
    0 0 0 ...1
    bk bk-1 bk-2...b0

    矩阵B为
    a0
    a1
    a2
    ...
    ak-1
    则ai = ai(i<k)
    = A^(i-k+1)*B最后一行的元素

    #include <set>
    #include <map>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    #define debug puts("here")
    
    const int MOD = 10000;
    const int X = 102;
    
    class Matrix{
    public:
        int n,m;
        int a[X][X];
    
        Matrix(){
            memset(a,0,sizeof(a));
        }
        Matrix(int _n,int _m):n(_n),m(_m){
            memset(a,0,sizeof(a));
        }
    
        Matrix operator * (Matrix p){
            int q = p.m;
            Matrix c(n,q);
            for(int i=0;i<n;i++)
                for(int j=0;j<q;j++)
                    for(int k=0;k<m;k++)
                        c.a[i][j] = (c.a[i][j]+a[i][k]*p.a[k][j])%MOD;
            return c;
        }
    
        void getE(){
            memset(a,0,sizeof(a));
            for(int i=0;i<n;i++)
                a[i][i] = 1;
        }
    
        Matrix bin(int exp){
            Matrix temp(n,n);
            temp.getE();
            Matrix cur = *this;
    
            while(exp>0){
                if(exp&1)
                    temp = temp*cur;
                cur = cur*cur;
                exp = exp >> 1;
            }
            return temp;
        }
    
        void di(){
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++)
                    cout<<a[i][j]<<" ";
                cout<<endl;
            }
            cout<<endl;
        }
    
    };
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("sum.in","r",stdin);
    #endif
    
        int n;
        while(cin>>n,n){
            Matrix a = Matrix(n,n);
            Matrix b = Matrix(n,1);
            for(int i=0;i<n-1;i++)
                a.a[i][i+1] = 1;
            for(int i=0;i<n;i++)
                scanf("%d",&b.a[i][0]);
            for(int i=0;i<n;i++)
                scanf("%d",&a.a[n-1][n-i-1]);
            int exp;
            cin>>exp;
            if(exp<n){
                printf("%d\n",b.a[exp][0]);
                continue;
            }
            exp ++;
            exp -= n;
            a = a.bin(exp);
            a = a*b;
            printf("%d\n",a.a[n-1][0]);
        }
    	return 0;
    }
    

      

    BZOJ 2875: [ NOI2012 ] 随机数生成器

    http://www.lydsy.com/JudgeOnline/problem.php?id=2875

    题目:f[n+1] = (f[n]+c)%m , 给出f[0],n,m,c,g,求f[n]%g

    分析:很明显可以构造矩阵

    A = a 1    B = f[0]

          0 1       c

    但是由于数据太大了,所以在矩阵乘法中间计算时会溢出,所以我们需要在乘的时候做一下处理。改为跟快速幂乘法相似的计算方式来防止溢出。具体看代码

    #include <set>
    #include <map>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef unsigned long long ll;
    
    #define debug puts("here")
    #define rep(i,n) for(int i=0;i<n;i++)
    #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
    #define pb push_back
    
    const int X = 5;
    
    ll MOD;
    
    class Matrix{
    public:
        int n,m;
        ll a[X][X];
    
        ll cal(ll x,ll y){
            ll sum = 0;
            while(y>0){
                if(y&1)
                    sum = (sum+x)%MOD;
                x = (x<<1)%MOD;
                y >>= 1;
            }
            return sum;
        }
    
        Matrix(){
            memset(a,0,sizeof(a));
        }
        Matrix(int _n,int _m):n(_n),m(_m){
            memset(a,0,sizeof(a));
        }
    
        Matrix operator * (Matrix p){
            int q = p.m;
            Matrix c(n,q);
            for(int i=0;i<n;i++)
                for(int j=0;j<q;j++)
                    for(int k=0;k<m;k++)
                        c.a[i][j] = (c.a[i][j]+cal(a[i][k],p.a[k][j]))%MOD;
            return c;
        }
    
        void getE(){
            memset(a,0,sizeof(a));
            for(int i=0;i<n;i++)
                a[i][i] = 1;
        }
    
        Matrix bin(ll exp){
            Matrix temp(n,n);
            temp.getE();
            Matrix cur = *this;
    
            while(exp>0){
                if(exp&1)
                    temp = temp*cur;
                cur = cur*cur;
                exp = exp >> 1;
            }
            return temp;
        }
    
        void di(){
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++)
                    cout<<a[i][j]<<" ";
                cout<<endl;
            }
            cout<<endl;
        }
    
    };
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("sum.in","r",stdin);
    #endif
    
        ll m,a,c,x0,n,g;
        while(cin>>m>>a>>c>>x0>>n>>g){
            MOD = m;
            Matrix ans(2,2);
            ans.a[0][0] = a;
            ans.a[0][1] = ans.a[1][1] = 1;
            ans = ans.bin(n);
            //ans.di();
            Matrix temp(2,1);
            temp.a[0][0] = x0;
            temp.a[1][0] = c;
            ans = ans*temp;
            cout<<ans.a[0][0]%g<<endl;
        }
    	return 0;
    }
    

      

    HOJ 2060 Fibonacci Problem Again

    题目:
    计算斐波那契数列[a,b]的和值对于1e9取模

    分析:
    对于斐波那契求第n项,我们可以构造矩阵
    A = 1 1 B = f[n]
          1 0        f[n-1]
    则f[n]为矩阵 A^n * B的第一项

    对于这题,我们可以额外构造多一维的矩阵出来为
           1 1 0           f[n]
    A = 1 0 0     B = f[n-1]
          1 0 1           sum[n-1]
    我们同样可以算出 sum[n] = A^n * B 的第三项

    #include <set>
    #include <map>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    #define debug puts("here")
    #define rep(i,n) for(int i=0;i<n;i++)
    #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
    #define pb push_back
    
    const int X = 5;
    const ll MOD = 1e9;
    
    class Matrix{
    public:
        int n,m;
        ll a[X][X];
    
        Matrix(){
            memset(a,0,sizeof(a));
        }
        Matrix(int _n,int _m):n(_n),m(_m){
            memset(a,0,sizeof(a));
        }
    
        Matrix operator * (Matrix p){
            int q = p.m;
            Matrix c(n,q);
            for(int i=0;i<n;i++)
                for(int j=0;j<q;j++)
                    for(int k=0;k<m;k++)
                        c.a[i][j] = (c.a[i][j]+a[i][k]*p.a[k][j])%MOD;
            return c;
        }
    
        void getE(){
            memset(a,0,sizeof(a));
            for(int i=0;i<n;i++)
                a[i][i] = 1;
        }
    
        Matrix bin(int exp){
            Matrix temp(n,n);
            temp.getE();
            Matrix cur = *this;
    
            while(exp>0){
                if(exp&1)
                    temp = temp*cur;
                cur = cur*cur;
                exp = exp >> 1;
            }
            return temp;
        }
    
        void di(){
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++)
                    cout<<a[i][j]<<" ";
                cout<<endl;
            }
            cout<<endl;
        }
    
    };
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("sum.in","r",stdin);
    #endif
    
        int n,m;
        while(scanf("%d%d",&n,&m),n||m){
            Matrix a = Matrix(3,3);
            a.a[0][0] = a.a[0][1] = a.a[1][0] = a.a[2][0] = a.a[2][2] = 1;
    
            Matrix f = Matrix(3,1);
            f.a[0][0] = 1;
            f.a[1][0] = 1;
            f.a[2][0] = 1;
    
            ll pre = 0;
            ll now = 0;
            if(n){
                Matrix x = a.bin(n-1);
                x = x*f;
                pre = x.a[2][0];
            }
            Matrix y = a.bin(m);
            y = y*f;
            now = y.a[2][0];
            ll mod = ll(1000000000);
            cout<<(now-pre+mod)%mod<<endl;
        }
    	return 0;
    }
    

    (HOJ 2255 Not Fibonacci这题跟上面的题目基本一模一样,代码略)

    HOJ 2930 Perfect Fill IIl

    详情看上一篇博文 http://www.cnblogs.com/yejinru/archive/2013/02/01/2888368.html

     

    4.HDU 2157 How many ways

    题目:
    给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值

    分析:
    把给定的图转为邻接矩阵,即A(i,j)=1当且仅当存在一条边i->j。令C=A*A,那么C(i,j)=ΣA(i,k)*A(k,j),实际上就等于从点i到点j恰好经过2条边的路径数(枚举k为中转点)。类似地,C*A的第i行第j列就表示从i到j经过3条边的路径数。同理,如果要求经过k步的路径数,我们只需要二分求出A^k即可。

    #include <set>
    #include <map>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    #define debug puts("here")
    #define rep(i,n) for(int i=0;i<n;i++)
    #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
    #define pb push_back
    
    const int MOD = 1000;
    const int X = 25;
    
    class Matrix{
    public:
        int n,m;
        int a[X][X];
    
        Matrix(){
            memset(a,0,sizeof(a));
        }
        Matrix(int _n,int _m):n(_n),m(_m){
            memset(a,0,sizeof(a));
        }
    
        Matrix operator * (Matrix p){
            int q = p.m;
            Matrix c(n,q);
            for(int i=0;i<n;i++)
                for(int j=0;j<q;j++)
                    for(int k=0;k<m;k++)
                        c.a[i][j] = (c.a[i][j]+a[i][k]*p.a[k][j])%MOD;
            return c;
        }
    
        void getE(){
            memset(a,0,sizeof(a));
            for(int i=0;i<n;i++)
                a[i][i] = 1;
        }
    
        Matrix bin(int exp){
            Matrix temp(n,n);
            temp.getE();
            Matrix cur = *this;
    
            while(exp>0){
                if(exp&1)
                    temp = temp*cur;
                cur = cur*cur;
                exp = exp >> 1;
            }
            return temp;
        }
    
        void di(){
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++)
                    cout<<a[i][j]<<" ";
                cout<<endl;
            }
            cout<<endl;
        }
    
    };
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("sum.in","r",stdin);
    #endif
    
        int n,m,x,y,k;
        while(scanf("%d%d",&n,&m),n||m){
            Matrix a = Matrix(n,n);
            while(m--){
                scanf("%d%d",&x,&y);
                a.a[x][y] = 1;
            }
            int cnt;
            cin>>cnt;
            while(cnt--){
                scanf("%d%d%d",&x,&y,&k);
                Matrix temp = a.bin(k);
                printf("%d\n",temp.a[x][y]);
            }
        }
    	return 0;
    }
    

      

     

    不会分类的几题:

    vijos 1049 送给圣诞夜的礼品

    顺次给出m个置换,反复使用这m个置换对初始序列进行操作,问k次置换后的序列。m<=10, k<2^31。
    首先将这m个置换“合并”起来(算出这m个置换的乘积),然后接下来我们需要执行这个置换k/m次(取整,若有余数则剩下几步模拟即可)。

    #include <set>
    #include <map>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    #define debug puts("here")
    
    const int MAXN = 102;
    const int MAXM = 11;
    
    int n,m;
    
    class Matrix{
    public:
        int a[MAXN][MAXN];
    
        Matrix(){
            memset(a,0,sizeof(a));
        }
    
        void setE(){
            memset(a,0,sizeof(a));
            for(int i=0;i<n;i++)
                a[i][i] = 1;
        }
    
        Matrix operator * (Matrix b){
            Matrix c = Matrix();
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                    for(int k=0;k<n;k++)
                        c.a[i][j] += a[i][k]*b.a[k][j];
            return c;
        }
    
        Matrix bin(int exp){
            Matrix ans;
            Matrix cur = *this;
            ans.setE();
            while(exp>0){
                if(exp&1)
                    ans = ans*cur;
                cur = cur*cur;
                exp >>= 1;
            }
            return ans;
        }
        void di(){
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++)
                    cout<<a[i][j]<<" ";
                cout<<endl;
            }
            cout<<endl;
        }
    };
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("sum.in","r",stdin);
    #endif
    
        int k;
        while(cin>>n>>m>>k){
            int x;
            Matrix ans;
            ans.setE();
            Matrix ret[12];
            ret[0].setE();
    
            for(int i=0;i<m;i++){
                Matrix cur;
                for(int j=0;j<n;j++){
                    scanf("%d",&x);
                    cur.a[j][x-1] = 1;
                }
                ret[i+1] = cur*ret[i];
                //ret[i+1].di();
                ans = cur*ans;
            }
    
            ans = ans.bin(k/m);
            ans = ret[k%m]*ans;
            //ans.di();
    
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++){
                    if(ans.a[i][j]){
                        if(i)
                            cout<<" ";
                        cout<<j+1;
                        break;
                    }
                }
            cout<<endl;
        }
    	return 0;
    }
    

      

    HOJ 2446 Cellular Automaton

    题目:
    在一个环中有n个格子,每个格子的值为ai,距离该格子不足d的所有格子的和对于
    m取余为新的值,问第k次变换后的所有n个格子的值

    分析:
    很容易可以构造出一个循环的矩阵出来,但是如果是O(n^3*logn)会TLE。
    我们可以注意到循环矩阵a * b只需要计算a的第一行*b,然后下面的移位均可以得
    到。时间为O(n^2*logn)

    #include <set>
    #include <map>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    #define debug puts("here")
    
    #define rep(i,n) for(int i=0;i<n;i++)
    
    #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
    
    #define pb push_back
    
    const int X = 505;
    
    ll a[X][X],c[X][X];
    ll ans[X];
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("sum.in","r",stdin);
    #endif
    
        int n,m,k,d;
        while(~scanf("%d%d%d%d",&n,&m,&d,&k)){
            rep(i,n)
                scanf("%lld",&ans[i]);
    
            rep(i,n)
                rep(j,n)
                    if( (i-j+n)%n<=d || (j-i+n)%n<=d )
                        a[i][j] = 1;
                    else
                        a[i][j] = 0;
    
            while(k>0){
                if(k&1){
                    rep(i,n){
                        c[0][i] = 0;
                        rep(j,n)
                            c[0][i] += ans[j]*a[j][i];
                    }
                    rep(i,n)
                        ans[i] = c[0][i]%m;
                }
    
                rep(i,n){
                    c[0][i] = 0;
                    rep(j,n)
                        c[0][i] += a[0][j]*a[j][i];
                }
                rep(i,n)
                    rep(j,n)
                        if(i==0)
                            a[i][j] = c[i][j]%m;
                        else
                            a[i][j] = a[i-1][(j-1+n)%n];
    
                k >>= 1;
            }
            rep(i,n-1)
                printf("%lld ",ans[i]);
            printf("%lld\n",ans[n-1]);
        }
    	return 0;
    }
    

      

    压缩矩阵

    poj 3318 Matrix Multiplication

    题目:
    判断矩阵a * b == c

    分析:
    方法一:
    O(n^3)算法提示会TLE,但是原矩阵是一个稀疏矩阵,所以可
    以在相乘的时候判断是否为0,这样同样不会TLE~~

    方法二:
    压缩矩阵,左乘1*n的矩阵,使得左边以及右边都变成1*n的
    矩阵,然后两边判断是否相等就行了~~但是如果这样压缩的话,
    不保证每个元素的特性,所以这个1*n的矩阵得要体现特性,构
    造的时候可以取随机数,或者令(1,2...n)

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    
    const int X = 505;
    #define debug puts("here");
    
    typedef __int64 ll;
    
    int n;
    
    void mul(ll a[X][X],ll *b){
        ll temp[X] = {0};
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                temp[i] += b[j]*a[j][i];
        for(int i=0;i<n;i++)
            b[i] = temp[i];
    }
    
    bool eq(ll a[],ll b[]){
        for(int i=0;i<n;i++)
            if(a[i]!=b[i])
                return false;
        return true;
    }
    
    ll a[X][X],b[X][X],c[X][X];
    ll q[X],p[X];
    
    int main(){
        freopen("sum.in","r",stdin);
        while(cin>>n){
            for(int i=0;i<n;i++)
                q[i] = p[i] = i+1;
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                    scanf("%I64d",&a[i][j]);
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                    scanf("%I64d",&b[i][j]);
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                    scanf("%I64d",&c[i][j]);
    
            mul(a,p);
            mul(b,p);
            mul(c,q);
    
            if(eq(p,q))
                puts("YES");
            else
                puts("NO");
        }
        return 0;
    }
    

     

    以后若还有的话,会更新一下的。。。

  • 相关阅读:
    nexus docker 私有镜像处理
    nexus 使用Raw Repositories 进行maven site 发布
    nexus && minio s3 存储私有镜像
    spring boot 使用spring.resources.static-locations 分离系统模版&&资源文件
    Tencent Server Web 安装试用
    docker could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network
    Tencent Server Web(TSW) 腾讯开源的nodejs 基础设施
    Stream Processing 101: From SQL to Streaming SQL in 10 Minutes
    13 Stream Processing Patterns for building Streaming and Realtime Applications
    Siddhi cep java 集成简单使用
  • 原文地址:https://www.cnblogs.com/yejinru/p/2890441.html
Copyright © 2011-2022 走看看