UVA 11149 Power of Matrix(矩阵+二分)

解决UVA 11149问题,通过矩阵快速幂算法结合二分查找,高效计算大指数下矩阵的幂,并只输出结果的最后一位数字。

此文章可以使用目录功能哟↑(点击上方[+])

 UVA Problem 11149 Power of Matrix

Accept: 0    Submit: 0
Time Limit: 3000 MS

 Problem Description



 Input

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.

 Output

For each case, your program should compute the matrix . 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

 Problem Idea

解题思路:

【题意】
给你一个n*n大小的矩阵A,和系数k,求的结果矩阵

由于数据比较大,输出结果矩阵时,每个元素只需输出最后一位数


【类型】
矩阵构造+二分

【分析】
求矩阵,显然是要用到矩阵乘法快速幂的

但是,如果单纯用快速幂求A~,那和直接一项项计算并没有什么区别,复杂度是O(n*n*n*k),显然不够

所以可以采取二分,对于

①当k为奇数时

②当k为偶数时


然后第一个括号里可以进一步化简,直至k=1为止

这里可以递归实现

一开始TLE了好几发,还以为递归实现还不够优化,后来才发现,题目指出,n=0时,输入结束,然而我却判断要0 0才退出

好吧,超时在这里,醉了

【时间复杂度&&优化】
O(n*n*nlogk)

题目链接→UVA 11149 Power of Matrix

 Source Code

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-8
#define LL long long
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 45;
const int M = 100005;
const int inf = 1000000007;
const int mod = 10;
typedef struct node
{
	int a[N][N];
	void Init()
	{
		memset(a,0,sizeof(a));
		for(int i=0;i<N;i++)
			a[i][i]=1;
	}
}matrix;
int n;
matrix mul(matrix a,matrix b)//矩阵乘法
{
	matrix ans;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
		{
			ans.a[i][j]=0;
			for(int k=0;k<n;k++)
				ans.a[i][j]+=(a.a[i][k]*b.a[k][j])%mod;
			ans.a[i][j]%=mod;
		}
	return ans;
}
matrix add(matrix a,matrix b)//矩阵加法
{
	matrix ans;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			ans.a[i][j]=(a.a[i][j]+b.a[i][j])%mod;
	return ans;
}
matrix pow(matrix a,int n)//求a^n
{
	matrix ans;
	ans.Init();
	while(n)
	{
		if(n%2)
			ans=mul(ans,a);
		n/=2;
		a=mul(a,a);
	}
	return ans;
}
matrix ans,s;
matrix dfs(int k)
{
    if(k==1)
        return ans;
    if(k%2)
        return add(mul(dfs(k/2),add(s,pow(ans,k/2))),pow(ans,k));
    else
        return mul(dfs(k/2),add(s,pow(ans,k/2)));
}
int main()
{
    int k,i,j;
    s.Init();
    while(scanf("%d%d",&n,&k)&&n)
    {
        for(i=0;i<n;i++)
            for(j=0;j<n;j++)
                scanf("%d",&ans.a[i][j]),ans.a[i][j]%=10;
        ans=dfs(k);
        for(i=0;i<n;i++)
            for(j=0;j<n;j++)
                printf("%d%c",ans.a[i][j],j!=n-1?' ':'\n');
        puts("");
    }
    return 0;
}

菜鸟成长记

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值