【模板】矩阵快速幂

题目背景

矩阵快速幂

题目描述

给定n*n的矩阵A,求A^k

输入输出格式

输入格式:

第一行,n,k

第2至n+1行,每行n个数,第i+1行第j个数表示矩阵第i行第j列的元素

输出格式:

输出A^k

共n行,每行n个数,第i行第j个数表示矩阵第i行第j列的元素,每个元素模10^9+7

输入输出样例

输入样例#1:
2 1
1 1
1 1
输出样例#1:
1 1
1 1

说明

n<=100, k<=10^12, |矩阵元素|<=1000 算法:矩阵快速幂

思路

这题有毒啊,没开长整型一个都不对,害得我以为我板子写错了QAQ

一个裸的矩阵快速幂,矩阵乘法要求两个矩阵分别为n行m列与m行p列,得出的矩阵是n行p列

矩阵乘法满足结合律,但不满足交换律(所以可以套快速幂的板子)

教科书告诉你,计算规则是,第一个矩阵第一行的每个数字(2 和1),各自乘以第二个矩阵第一列对应位置的数字(1 和1),然后将乘积相加( 2 x 1 + 1 x 1),得到结果矩阵左上角的那个值3。

这里写图片描述

OK,但是我的这个快速幂有一点不同就是ans数组的初值不是1,而是输入的数,我们计算的是k-1次方

默认为2次方,所以要-1,赋值为1有问题的

感谢@ht008(一个萌妹纸)

代码实现

 1 #include<cstdio>
 2 #define LL long long
 3 const int maxn=1e3+10;
 4 LL n,k;
 5 LL x[maxn][maxn],dx[maxn][maxn],ans[maxn][maxn];
 6 const int mod=1e9+7;
 7 void AC(LL n){
 8     for(int i=1;i<=n;i++)
 9     for(int j=1;j<=n;j++)
10     dx[i][j]=ans[i][j],ans[i][j]=0;
11     for(int i=1;i<=n;i++)
12     for(int j=1;j<=n;j++)
13     for(int k=1;k<=n;k++)
14     ans[i][j]=(ans[i][j]+(x[i][k]*dx[k][j])%mod)%mod;
15 }
16 void XC(LL n){
17     for(int i=1;i<=n;i++)
18     for(int j=1;j<=n;j++)
19     dx[i][j]=x[i][j],x[i][j]=0;
20     for(int i=1;i<=n;i++)
21     for(int j=1;j<=n;j++)
22     for(int k=1;k<=n;k++)
23     x[i][j]=(x[i][j]+(dx[i][k]*dx[k][j])%mod)%mod;
24 }
25 void FP(LL n,LL k){
26     while(k){
27         if(k&1) AC(n);
28         k>>=1;
29         XC(n);
30     }
31 }
32 int main(){
33     scanf("%lld%lld",&n,&k);
34     for(int i=1;i<=n;i++)
35     for(int j=1;j<=n;j++)
36     scanf("%lld",&x[i][j]),ans[i][j]=x[i][j];
37     FP(n,k-1);
38     for(int i=1;i<=n;i++){
39         for(int j=1;j<=n;j++) printf("%lld ",ans[i][j]);
40         putchar('\n');
41     }
42     return 0;
43 }

 

posted @ 2017-08-26 16:25  J_william  阅读(285)  评论(0编辑  收藏  举报