zoukankan      html  css  js  c++  java
  • UVA 11149 Power of Matrix 快速幂

    题目链接:

    http://acm.hust.edu.cn/vjudge/contest/122094#problem/G

    Power of Matrix

    Time Limit:3000MS
    Memory Limit:0KB
    #### 问题描述 > 给你一个矩阵A,求A+A^2+A^3+...+A^k #### 输入 > Input consists of no more than 20 test cases. The first line for each case contains two positive integers n > (≤ 40) and k (≤ 1000000). This is followed by n lines, each containing n non-negative integers, giving > the matrix A. > Input is terminated by a case where n = 0. This case need NOT be processed.

    输出

    For each case, your program should compute the matrix A + A2 + A3 + . . . + Ak
    . Since the values may
    be very large, you only need to print their last digit. Print a blank line after each case.

    样例

    sample input
    3 2
    0 2 0
    0 0 2
    0 0 0
    0 0

    sample output
    0 2 4
    0 0 2
    0 0 0

    题解

    A+A2+...Ak=(I+A(n/2))(A+...+A(n/2))=...
    一直递推下去,深度只有logn,只要logn次快速幂求A^x。

    代码

    WA四次的代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    
    const int maxn = 55;
    const int mod = 10;
    typedef int LL;
    
    
    struct Matrix {
    	LL mat[maxn][maxn];
    	Matrix() { memset(mat, 0, sizeof(mat)); }
    	friend Matrix operator *(const Matrix& A, const Matrix& B);
    	friend Matrix operator +(const Matrix &A,const Matrix &B);
    	friend Matrix operator ^(Matrix A, int n);
    };
    
    Matrix I;
    
    Matrix operator +(const Matrix& A, const Matrix& B) {
    	Matrix ret;
    	for (int i = 0; i < maxn; i++) {
    		for (int j = 0; j < maxn; j++) {
    			ret.mat[i][j] = (A.mat[i][j] + B.mat[i][j])%mod;
    		}
    	}
    	return ret;
    }
    
    Matrix operator *(const Matrix& A, const Matrix& B) {
    	Matrix ret;
    	for (int i = 0; i < maxn; i++) {
    		for (int j = 0; j < maxn; j++) {
    			for (int k = 0; k < maxn; k++) {
    				ret.mat[i][j] = (ret.mat[i][j]+A.mat[i][k] * B.mat[k][j]) % mod;
    			}
    		}
    	}
    	return ret;
    }
    
    Matrix operator ^(Matrix A, int n) {
    	Matrix ret=I;
    	while (n) {
    		if (n & 1) ret = ret*A;
    		A = A*A;
    		n /= 2;
    	}
    	return ret;
    }
    
    Matrix solve(Matrix A, int n) {
    	if (!n) return I;
    	if (n == 1) return A;
    	//这里要加括号!!!  ret=I+(A^(n/2))!!!
    	Matrix ret = I + A ^ (n / 2);
    	ret = ret*solve(A, n / 2);
    	//这里也要加!!!! ret=ret+(A^n)!!!
    	if (n % 2) ret = ret + A^n;
    	return ret;
    }
    
    int n, k;
    
    int main() {
    	for (int i = 0; i < maxn; i++) I.mat[i][i] = 1;
    	while (scanf("%d%d", &n, &k) == 2 && n) {
    		Matrix A;
    		for (int i = 0; i < n; i++) {
    			for (int j = 0; j < n; j++) {
    				scanf("%d", &A.mat[i][j]);
    				A.mat[i][j] %= mod;
    			}
    		}
    		Matrix ans=solve(A, k);
    		for (int i = 0; i < n; i++) {
    			for (int j = 0; j < n-1; j++) {
    				printf("%d ",ans.mat[i][j]);
    			}
    			printf("%d
    ", ans.mat[i][n - 1]);
    		}
    		printf("
    ");
    	}
    	return 0;
    }
    

    保险一些的写法:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    
    const int maxn = 55;
    const int mod = 10;
    typedef int LL;
    
    
    struct Matrix {
    	LL mat[maxn][maxn];
    	Matrix() { memset(mat, 0, sizeof(mat)); }
    	friend Matrix operator *(const Matrix& A, const Matrix& B);
    	friend Matrix operator +(const Matrix &A,const Matrix &B);
    	friend Matrix pow(Matrix A, int n);
    };
    
    Matrix I;
    
    Matrix operator +(const Matrix& A, const Matrix& B) {
    	Matrix ret;
    	for (int i = 0; i < maxn; i++) {
    		for (int j = 0; j < maxn; j++) {
    			ret.mat[i][j] = (A.mat[i][j] + B.mat[i][j])%mod;
    		}
    	}
    	return ret;
    }
    
    Matrix operator *(const Matrix& A, const Matrix& B) {
    	Matrix ret;
    	for (int i = 0; i < maxn; i++) {
    		for (int j = 0; j < maxn; j++) {
    			for (int k = 0; k < maxn; k++) {
    				ret.mat[i][j] = (ret.mat[i][j]+A.mat[i][k] * B.mat[k][j]) % mod;
    			}
    		}
    	}
    	return ret;
    }
    
    Matrix pow(Matrix A, int n) {
    	Matrix ret=I;
    	while (n) {
    		if (n & 1) ret = ret*A;
    		A = A*A;
    		n /= 2;
    	}
    	return ret;
    }
    
    Matrix solve(Matrix A, int n) {
    	if (!n) return I;
    	if (n == 1) return A;
    	Matrix ret = I + pow(A,n/2);
    	ret = ret*solve(A, n / 2);
    	if (n % 2) ret = ret + pow(A,n);
    	return ret;
    }
    
    int n, k;
    
    int main() {
    	for (int i = 0; i < maxn; i++) I.mat[i][i] = 1;
    	while (scanf("%d%d", &n, &k) == 2 && n) {
    		Matrix A;
    		for (int i = 0; i < n; i++) {
    			for (int j = 0; j < n; j++) {
    				scanf("%d", &A.mat[i][j]);
    				A.mat[i][j] %= mod;
    			}
    		}
    		Matrix ans=solve(A, k);
    		for (int i = 0; i < n; i++) {
    			for (int j = 0; j < n-1; j++) {
    				printf("%d ",ans.mat[i][j]);
    			}
    			printf("%d
    ", ans.mat[i][n - 1]);
    		}
    		printf("
    ");
    	}
    	return 0;
    }
  • 相关阅读:
    熟练使用有棱有角的内存
    计算机进行小数运算时出错的原因
    数据是用二进制数表示的
    代码之外的功夫
    运行库实现
    系统调用与API
    运行库
    内存
    Windows下的动态链接
    Sharding-JDBC 实现垂直分库水平分表
  • 原文地址:https://www.cnblogs.com/fenice/p/5679392.html
Copyright © 2011-2022 走看看