• 矩阵幂求和


    题意:

      给矩阵A,求Σi=(1,k) A

    SOL:

      虽然可以快速幂,然而还是会炸,那么我们就优化一下。。。

      

      若k是偶数,则S=(1+1^(k/2))(A^1+A^2+……+A^(k/2))

      若k是奇数,则S=(1+1^(k/2))(A^1+A^2+……+A^(k/2))+A^k

      像是快速幂套快速幂。。。。复杂度。。一个log还是两个log呢。。

    Code:

      

    #include <iostream>
    #include <cstdio>
    using namespace std;
    
    int n, m;
    struct Matrix
    {
    	int x[31][31];
    };
    
    void matrixPrint(Matrix mat)	
    {
    	for (int i = 0; i < n; ++i)
    	{
    		for (int j = 0; j < n; ++j)
    		{
    			if (j > 0) printf(" ");
    			printf("%d", mat.x[i][j]);
    		}
    		printf("
    ");
    	}
    }
    
    Matrix matrixMultiply(Matrix a, Matrix b)	
    {
    	Matrix ret;
    	for (int i = 0; i < n; ++i)
    	{
    		for (int j = 0; j < n; ++j)
    		{
    			ret.x[i][j] = 0;
    			for (int t = 0; t < n; ++t)
    			{
    				ret.x[i][j] += a.x[i][t] * b.x[t][j];
    				if (ret.x[i][j] >= m) ret.x[i][j] %= m;
    			}
    		}
    	}
    	return ret;
    }
    
    Matrix matrixPow(Matrix mat, int p)	
    {
    	Matrix ret;
    	Matrix tmp = mat;
    	for (int i = 0; i < n; ++i)
    	{
    		ret.x[i][i] = 1;
    		for (int j = i + 1; j < n; ++j)
    		{
    			ret.x[i][j] = 0;
    			ret.x[j][i] = 0;
    		}
    	}
    	while (p > 0)
    	{
    		if (p & 1) ret = matrixMultiply(ret, tmp);
    		p >>= 1;
    		tmp = matrixMultiply(tmp, tmp);
    	}
    	return ret;
    }
    
    Matrix matrixSummary(Matrix mat, int k)
    {
    	for (int i = 0; i < n; ++i)
    	{
    		for (int j = 0; j < n; ++j)
    		{
    			if (mat.x[i][j] >= m) mat.x[i][j] %= m;
    		}
    	}
    
    	if (k == 1) return mat;
    	Matrix M1 = matrixPow(mat, k / 2);
    	for (int i = 0; i < n; ++i)
    	{
    		M1.x[i][i] += 1;
    	}
    	Matrix M2 = matrixSummary(mat, k / 2);
    	Matrix ret = matrixMultiply(M1, M2);
    	if (k & 1)
    	{
    		Matrix tmp = matrixPow(mat, k);
    		for (int i = 0; i < n; ++i)
    		{
    			for (int j = 0; j < n; ++j)
    			{
    				ret.x[i][j] += tmp.x[i][j];
    				if (ret.x[i][j] >= m) ret.x[i][j] %= m;
    			}
    		}
    	}
    	return ret;
    }
    
    int main()
    {
    	Matrix mat;
    	int k;
    	scanf("%d%d%d", &n, &k, &m);
    	for (int i = 0; i < n; ++i)
    	{
    		for (int j = 0; j < n; ++j)
    		{
    			scanf("%d", &mat.x[i][j]);
    		}
    	}
    	Matrix ret = matrixSummary(mat, k);
    	matrixPrint(ret);
    	return 0;
    }
    

     貌似还有更牛逼的。。。到时候再学下好了。。。

    Sometimes it s the very people who no one imagines anything of. who do the things that no one can imagine.
  • 相关阅读:
    Java 链表
    知识点归列
    HTML和CSS必须知道的重点难点问题
    函数表达式
    javascript原型链
    canvas成长树
    checkbox选中问题
    使用vue-cli脚手架自定义iview主题
    AI学习吧-Redis操作-事务、订阅
    AI学习吧-REDIS-常识
  • 原文地址:https://www.cnblogs.com/YCuangWhen/p/5269445.html
Copyright © 2020-2023  润新知