幼稚园的矩阵 | ||||||
| ||||||
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矩阵
0 | A |
0 | 0 |
转换矩阵
1 | 0 |
1 | A |
#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
**/