Tr A - 杭电1575(矩阵快速幂模板)

题目链接: Tr A-杭电1575

                                                   Tr A

                       Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
                                             Total Submission(s): 8088    Accepted Submission(s): 5883

Problem Description

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

 

Input

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

Output

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

Sample Iutput

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

 

 

Sample Output

2
2686

 

题意描述:

给你一个 n(1阶方阵,让你计算出它的 k 次方(不用输出),并且最后输出它主对角线的所有元素之和。中间还有一个取模运算,意思是每次计算的值都要对 9973 进行取模,使它处于 0~9972 

 

思想解析:

题目样例中给了 99999999 次方,所以肯定不能直接去算,直接算肯定超时的,所以这就涉及到了快速幂的思想,可以这么解释:每个十进制数都可以变换成二进制,比如21,换成二进制是10101,也就是 21 = 1+4+16 ,而计算机存储数字的方法就是变换成二进制,所以这个数的二进制位为 1 的时候,就乘,不是 1,就自乘。所以可以用右移的方法,来控制乘不乘

有关快速幂思想的,可以参考整数快速幂这个博客,这里面讲的比较详细。

 

代码篇:

#include 
#include 
#include 
using namespace std;
struct Ride      ///用结构体来存放矩阵比较方便
{
    int e[20][20];
};
int n;

Ride ride(Ride a,Ride b) ///两个矩阵相乘
{
    Ride c;
    memset(c.e,0,sizeof(c.e));
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            for(int k=1; k<=n; k++)
                c.e[i][j] = (c.e[i][j] + a.e[i][k] * b.e[k][j]) % 9973;
    return c;
}
int main()
{
    Ride rec,ans;
    int t,k,sum;
    cin >> t;
    while(t--)
    {
        sum=0;
        scanf("%d %d",&n,&k);
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                scanf("%d",&rec.e[i][j]);

        memset(ans.e,0,sizeof(ans.e));///将ans矩阵变成单位矩阵
        for(int i=1; i<=n; i++)
            ans.e[i][i]=1;

        while(k)
        {
            if(k & 1) ///当k的最后一位是1时,ans*rec
                ans=ride(ans,rec);
            rec=ride(rec,rec);///每次循环 rec都要自乘
            k >>= 1; ///k右移,相当于k/2
        }

//        for(int i=1; i<=n; i++)    ///输出矩阵
//        {
//            for(int j=1; j<=n; j++)
//                printf("%d ",ans.e[i][j]);
//            cout << endl;
//        }

        for(int i=1; i<=n; i++) ///计算对角线和
            sum = (sum+ans.e[i][i]) % 9973;
        cout << sum % 9973 << endl;
    }
    return 0;
}

 

你可能感兴趣的:(算法)