P3390 【模板】矩阵快速幂

题目传送门

题目背景

矩阵快速幂

题目描述

给定 n×n 的矩阵 A,求 Ak

输入格式

第一行两个整数 n,k 接下来 n 行,每行 n 个整数,第 i 行的第 的数表示 Ai,j

输出格式

输出 A^k

共 n 行,每行 n 个数,第 i 行第 j 个数表示 (Ak)i,j,每个元素对 10^9+7 取模。

输入输出样例

输入 #1
2 1
1 1
1 1
输出 #1
1 1
1 1

嗯,好吧,步入正题,这是一道洛谷的模板题,本以为能爆踩他的我,结果可想而知。

后来,我总结了一下错误原因,结果发现,我原来主函数里少写一行代码(就无语),然后我就又又又瞎想了一些奇奇怪怪的东西:

快速幂其实就是用的递归公式:

所以,我们用这个推出的代码就应该长这样:

while版:

1 while(x>0) {
2     if(x%2!=0) ans=ans*a;
3         a=a*a;
4         x=x>>1;
5 }

递归版:

 1 int K(int a,int n){
 2     if(n==0)    
 3             return 1;
 4     if(n==1)    
 5             return a;
 6     int c=K(a,n/2);
 7     if(n%2==0)    
 8             return c*c;
 9     else    
10             return c*c*a;
11 }    

这说明什么???我们可以用这几段代码稍加修改,把它变成这道题的代码

BUT:!!!它超时了(TLE)

while也不行

呵呵,所以经过我的精心修改,正确的代码他终于来了!!

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<string>
 5 #include<cstring>
 6 #define LL long long//我真懒,呵呵 
 7 #define MOD 1000000007
 8 using namespace std;
 9 LL a[109][109],ans[109][109],cil[109][109],K;//个人习惯 
10 int n;
11 void Fk() {
12     while(K) {
13         if(K%2) {
14             for(int i=1; i<=n; i++)
15                 for(int j=1; j<=n; j++)
16                     cil[i][j]=ans[i][j],ans[i][j]=0;
17             for(int i=1; i<=n; i++)
18                 for(int j=1; j<=n; j++)
19                     for(int k=1; k<=n; k++)
20                         ans[i][j]=(ans[i][j]+cil[i][k]*a[k][j]%MOD)%MOD;
21         }
22         for(int i=1; i<=n; i++)
23             for(int j=1; j<=n; j++)
24                 cil[i][j]=a[i][j],a[i][j]=0;
25         for(int i=1; i<=n; i++)
26             for(int j=1; j<=n; j++)
27                 for(int k=1; k<=n; k++)
28                     a[i][j]=(a[i][j]+cil[i][k]*cil[k][j]%MOD)%MOD;
29 
30         K/=2;
31     }
32 }
33 int main() {
34     scanf("%d%lld",&n,&K);
35     for(int i=1; i<=n; i++)
36         for(int j=1; j<=n; j++)
37             scanf("%lld",&a[i][j]);
38 
39     for(int i=1; i<=n; i++)
40         for(int j=1; j<=n; j++)
41             ans[i][j]=a[i][j];
42 
43 
44     K--;
45     Fk();
46 
47     for(int i=1; i<=n; i++) {
48         for(int j=1; j<=n; j++) printf("%lld ",ans[i][j]);
49         puts("");
50     }
51     return 0;
52 }

我滴CSDN博客

posted on 2022-07-29 15:28  Larryhui  阅读(101)  评论(0)    收藏  举报