Hdu 1575.Tr A C and C++

本文介绍了一种使用矩阵快速幂算法解决求矩阵A的k次方的迹对9973取余问题的方法。通过C和C++实现,详细解释了矩阵乘法和快速幂的原理,以及如何在代码中应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1575

题目:

A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973。 

 Input:

数据的第一行是一个T,表示有T组数据。
每组数据的第一行有n(2 <= n <= 10)和k(2 <= k < 10^9)两个数据。接下来有n行,每行有n个数据,每个数据的范围是[0,9],表示方阵A的内容。

Output: 

对应每组数据,输出Tr(A^k)%9973。

Sample Input: 

2
2 2
1 0
0 1
3 99999999
1 2 3
4 5 6
7 8 9

 Sample Output:

2

2686

 初次邂逅此题好像有点无从下手,百度了别人的思路,才明白如何做。矩阵乘的问题,又因为太多数据连乘会TLE,所以运用了矩阵快速幂的思想,具体思路会在下面链接别人的博客。写此题就是想练习一下C++的重载 * 运算符。

 

C代码:

#include<stdio.h>
#include<stdlib.h>
typedef struct matrix {
	int ar[11][11];
}matrix;
matrix ans,res;
matrix Mul(matrix A,matrix B,int n)
{
	int i,j,k;
	matrix temp;
	for (i = 0;i < n;i++)
	{
		for (j = 0;j < n;j++)
		{
			temp.ar[i][j] = 0;   //此处数组要初始化0
			for (k = 0;k < n;k++)
			{
				temp.ar[i][j] += A.ar[i][k] * B.ar[k][j];
			}
			temp.ar[i][j] %= 9973;   //数据太大,取余
		}
	}
	return temp;
}
matrix Pow(int n,int k)
{
	int i,j;
	for (i = 0;i < n;i++)
	{
		for (j = 0;j < n;j++){
			ans.ar[i][j] = (i == j);
		}
	}
	while (k)
	{
		if (k & 1)
			ans = Mul(ans,res,n);
		res = Mul(res,res,n);
		k >>= 1;
	}
}
int main()
{
	int T;
	scanf("%d",&T);
	while (T--)
	{
		int i,j,n,k;
		scanf("%d %d",&n,&k);
		for (i = 0;i < n;i++)
		{
			for (j = 0;j < n;j++){
				scanf("%d",&res.ar[i][j]);
			}
		}
		Pow(n,k);
		int sum = 0;
		for (i = 0;i < n;i++)
			sum += ans.ar[i][i];
		printf("%d\n",sum % 9973);
	}
	return 0;
}

 

C++代码:

我想把operator* 函数定义在外部,可是就会提示参数个数问题,可定义写在外部,就得用 友元friend,但就不是成员函数了。希望大神可以指点一下

#include<iostream>
using namespace std;
#define SIZE 11
#define MOD 9973
int n;
class item {
public:
	item() = default;
	int ar[SIZE][SIZE];
	item operator *(const item &rhs)
	{
		item temp;
	int i,j,k;
	for (i = 0; i < n;i++)
	{
		for (j = 0;j < n;j++)
		{
			temp.ar[i][j] = 0;
			for (k = 0;k < n;k++)
			{
				temp.ar[i][j] += ar[i][k] * rhs.ar[k][j];
			}
			temp.ar[i][j] %= MOD;
		}
	}
	return temp;
	}
	void pow(int k);
};
item ans,res;
void item::pow(int k)
{
	int i,j;
	for (i = 0;i < n;i++)
	{
		for (j = 0;j < n;j++){
			ans.ar[i][j] = (i == j);
		}
	}
	while (k)
	{
		if (k & 1)
			ans = ans * res;
		res = res * res ;
		k >>= 1;
	}
}
int main()
{
	int T;
	cin >> T;
	while (T--)
	{
		int i,j,k;
		cin >> n >> k;
		for (i = 0;i < n;i++)
		{
			for (j = 0;j < n;j++)
			{
				cin >> res.ar[i][j];
			}
		}
		res.pow(k);
		int sum = 0;
		for (i = 0;i < n;i++)
			sum += ans.ar[i][i];
		printf("%d\n",sum % 9973);
	}
	return 0;
}

 

参考:https://www.cnblogs.com/cmmdc/p/6936196.html

谢谢。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值