杭电1575(矩阵快速幂+求矩阵k次幂的迹模9973的值)

3 篇文章 0 订阅

Tr A

Time Limit: 1000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)

Problem Description

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

思路:

题意:求 n * n 矩阵的 k 次幂的迹,再模9973的值。

方法:矩阵快速幂

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define maxn 110

struct matrix{
    int a[maxn][maxn];
}m1,m2;

int n,k;//n*n矩阵的k次方 

//矩阵乘法 
matrix matrixmul(matrix m1,matrix m2)
{
    matrix result;
    memset(result.a,0,sizeof(result.a));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            for(int k=1;k<=n;k++)
            {
                result.a[i][j]+=m1.a[i][k]*m2.a[k][j];
                result.a[i][j]%=9973;//每次加完要对9973取模 
            }
        }
    }
    return result;
} 

//矩阵快速幂 
matrix matrixpow(matrix m1,int k)
{
    matrix result;
    memset(result.a,0,sizeof(result.a));//初始化 
    for(int i=1;i<=n;i++)
    {
        result.a[i][i]=1;//将result化为单位矩阵 
    }
    while(k!=0)//幂不为0时 
    {
        //k为奇数时,第一次乘法的结果为矩阵本身
        //所以要将m1乘以目前为单位矩阵的result
        //然后k-- 
        if(k%2!=0)
        {
            result=matrixmul(m1,result);
            k-=1;
        }
        //k为偶数时,将m1乘以m1,相当于乘了两次 
        //将幂k除以2 
        else
        {
            m1=matrixmul(m1,m1);
            k/=2;
        }
    }
    return result;
}

/*
一种代码较少的模板,结果同样AC
matrix matrixpow(matrix m1,int k)
{
    if(k==1) return m1;
    matrix result=matrixpow(m1,k/2);
    result=matrixmul(result,result);
    if(k%2!=0) result=matrixmul(result,m1);
    return result;
}
*/

int main()
{
    int sum;//矩阵的迹 
    int t; 
    cin>>t;
    while(t--)
    {
        cin>>n>>k;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                cin>>m1.a[i][j];
                m1.a[i][j]%=9973;//注意避免溢出 
            }
        }
        m2=matrixpow(m1,k);
        sum=0;
        for(int i=1;i<=n;i++)
        {
            sum+=m2.a[i][i];//主对角线上各项和 
            sum%=9973;
        }
        cout<<sum<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值