HRBUST 1855 幼稚园的矩阵(矩阵快速幂)

幼稚园的矩阵
Time Limit: 1000 MSMemory Limit: 32768 K
Total Submit: 21(8 users)Total Accepted: 11(6 users)Rating: Special Judge: No
Description
    Koko在 AK_PUSH前辈的悉心调教下,终于学会了传说中只有小学生才会的矩阵快速幂心法, AK_PUSH前辈为了测试一下coco掌握得怎么样,决定调戏一下koko,只见前辈从怀里掏出一对金银大笔,两支笔在空中飞快的飘舞,天地元气疯狂汇聚,霎时间,天地间一片金光四射,刺得人睁不开眼,待得金色褪去,只见一个金色大字以迅雷不及掩耳盗铃之势向koko飞奔而来!Koko定睛一看这大字中竟然有传说中大学生才会的天地法则!Koko运起矩阵快速幂心法再看,这天地法则居然蕴含着一个矩阵A!Koko提起全身法力,睁开了他的第三只眼——钛合金。。。眼,只见这矩阵旁还有一行小字:计算A + A2 + A3 + ... + Ak.(Ak = A * A * ... * A (k 次))。
你的任务是,编写一个程序,帮助koko化解 AK_PUSH前辈的金色大字。
Input

    输入以T开始,代表测试样例的个数(T<=20),每组样例以两个整数N(1≤N≤30)和K(1≤K≤10^9)开始。下面n行每行包含n个非负整数(均不大于10)。

Output

    法则看上去是残缺不全的,因此你不必输出每个位置的结果,只需要输出答案每个位置的最后一位数字。

Sample Input
2
3 2
1 4 6
6 5 2
1 2 3
3 10
1 4 6
6 5 2
1 2 3
Sample Output
Case 1:
208
484
722
Case 2:
868
620
546
Author
小伙伴们@哈商大
矩阵快速幂

推导关系式

Sn=A*Sn-1+A;

推导关系矩阵 

s0矩阵

0A
00

转换矩阵

10
1A

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n,k,m;
struct Matris///矩阵
{
    int r,c;
    int mat[110][110];
};
Matris Matris_Mul(Matris a,Matris b)
{
    Matris tem;///temporary(暂时变量(背背英语勿怪))
    memset(tem.mat,0,sizeof(tem.mat));
    tem.c=a.c;///行
    tem.r=b.r;///列
    for(int i=0; i<tem.c; i++)
    {
        for(int j=0; j<tem.r; j++)
        {
            for(int k=0; k<tem.r; k++)
            {
                tem.mat[i][j]+=((a.mat[i][k])*(b.mat[k][j]%));
                tem.mat[i][j]%=m;
            }
        }
    }
    return tem;
}

int main()
{
    int T;
    int Case=0;
    while(~scanf("%d%d%d",&n,&k,&m))
    {
        Matris tem,res;

        memset(tem.mat,0,sizeof(tem.mat));
        memset(res.mat,0,sizeof(res.mat));
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n; j++)
            {
                scanf("%d",&res.mat[i][j+n]);
                tem.mat[i+n][j+n]=res.mat[i][j+n];
            }
        }
        tem.c=tem.r=res.c=res.r=2*n;
        for(int i=0; i<n; i++)
        {
            tem.mat[i][i]=tem.mat[i+n][i]=1;
        }
        while(k)
        {
            if(k&1)
            {
                res=Matris_Mul(res,tem);
            }
            tem=Matris_Mul(tem,tem);
            k/=2;
        }
       // printf("Case %d:\n",++Case);
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n; j++)
            {
                printf("%d",res.mat[i][j]);
                if(j!=n-1)
                    printf(" ");
            }
            printf("\n");
        }
    }

}
/**
10
3 1
1 4 6
6 5 2
1 2 3
3 2
1 4 6
6 5 2
1 2 3
3 3
1 4 6
6 5 2
1 2 3
3 4
1 4 6
6 5 2
1 2 3
**/



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值