矩阵乘法

51nod 1113 矩阵快速幂

模版题

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cmath>
 7 #include <map>
 8 #define ll long long
 9 #define out(a) printf("%lld ",a)
10 #define ln printf("\n")
11 const int N=1e2+50;
12 const int MOD=1e9+7;
13 using namespace std;
14 int n,m;
15 ll a[N][N],b[N][N],c[N][N],ret[N][N];
16 int read()
17 {
18     int s=0,t=1; char c=getchar();
19     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
20     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
21     return s*t;
22 }
23 ll readl()
24 {
25     ll s=0,t=1; char c=getchar();
26     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
27     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
28     return s*t;
29 }
30 void mul(ll a[N][N],ll b[N][N],int n)
31 {
32     ll sum=0;
33     memset(c,0,sizeof(c));
34     for (int i=1;i<=n;i++){
35       for (int j=1;j<=n;j++){
36         sum=0;
37         for (int k=1;k<=n;k++)
38           sum+=(ll)(a[i][k]*b[k][j])%MOD;
39         c[i][j]=sum%MOD;
40       }
41     }
42     for (int i=1;i<=n;i++)
43       for (int j=1;j<=n;j++)
44         a[i][j]=c[i][j];
45 }
46 void Pow()
47 {
48     for (int i=1;i<=n;i++)
49       ret[i][i]=1;
50     while (m){
51       if (m&1) mul(ret,a,n);
52       mul(a,a,n);
53       m>>=1;
54     }
55 }
56 int main()
57 {
58     n=read(); m=read();
59     for (int i=1;i<=n;i++)
60       for (int j=1;j<=n;j++)
61         a[i][j]=readl();
62     Pow();
63     for (int i=1;i<=n;i++){
64       for (int j=1;j<=n;j++)
65         out(ret[i][j]);
66       ln;
67     }
68     return 0;
69 }
View Code

 #10220. 「一本通 6.5 例 2」Fibonacci 第 n 项

经典题

构造一个 矩阵然后直接矩乘快速幂就行。

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cmath>
 7 #include <map>
 8 #define ll long long
 9 #define out(a) printf("%lld",a)
10 #define ln printf("\n")
11 const int N=3;
12 const int MOD=1e9+7;
13 using namespace std;
14 ll n;
15 ll mod;
16 ll a[N][N],b[N][N],c[N][N],ret[N][N];
17 int read()
18 {
19     int s=0,t=1; char c=getchar();
20     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
21     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
22     return s*t;
23 }
24 ll readl()
25 {
26     ll s=0,t=1; char c=getchar();
27     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
28     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
29     return s*t;
30 }
31 void mul(ll a[N][N],ll b[N][N])
32 {
33     memset(c,0,sizeof(c));
34     for (int i=1;i<=2;i++)
35       for (int j=1;j<=2;j++){
36           ll sum=0;
37           for (int k=1;k<=2;k++)
38             sum+=(ll)(a[i][k]*b[k][j])%mod;
39             c[i][j]=sum%mod;
40       }
41     for (int i=1;i<=2;i++)
42       for (int j=1;j<=2;j++)
43         a[i][j]=c[i][j];
44 }
45 void Pow()
46 {
47     for (int i=1;i<=2;i++)
48       ret[i][i]=1;
49     while (n){
50       if (n&1) mul(ret,a);
51       mul(a,a);
52       n>>=1;
53     }
54 }
55 int main()
56 {
57     n=readl(),mod=readl(); n-=2;
58     a[1][1]=1; a[1][2]=1;
59     a[2][1]=1; a[2][2]=0;
60     Pow();
61     out((ret[1][1]%mod+ret[2][1]%mod)%mod);
62     return 0;
63 }
View Code

 

#10221. 「一本通 6.5 例 3」Fibonacci 前 n 项和

求斐波那契数列前n项和。

设第n项和为s[n],构造一个1*3的矩阵s[n] f[n] f[n-1]

根据

s[n]=s[n-1]+f[n];

f[n+1]=f[n]+f[n-1];

构造矩阵同理矩乘快速幂。

一次过就很舒服....

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cmath>
 7 #include <map>
 8 #define ll long long
 9 #define out(a) printf("%lld ",a)
10 #define ln printf("\n")
11 const int N=4;
12 const int MOD=1e9+7;
13 using namespace std;
14 ll n;
15 ll mod,ans;
16 ll a[N][N],b[N][N],c[N][N],ret[N][N];
17 int read()
18 {
19     int s=0,t=1; char c=getchar();
20     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
21     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
22     return s*t;
23 }
24 ll readl()
25 {
26     ll s=0,t=1; char c=getchar();
27     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
28     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
29     return s*t;
30 }
31 void mul(ll a[N][N],ll b[N][N])
32 {
33     memset(c,0,sizeof(c));
34     for (int i=1;i<=3;i++)
35       for (int j=1;j<=3;j++){
36         ll sum=0; 
37         for (int k=1;k<=3;k++)
38           sum+=(ll)(a[i][k]*b[k][j])%mod;
39         c[i][j]=sum%mod; 
40       }
41     for (int i=1;i<=3;i++)
42       for (int j=1;j<=3;j++)
43         a[i][j]=c[i][j];
44 }
45 void Pow()
46 {
47     for (int i=1;i<=3;i++)
48       ret[i][i]=1;
49     while (n){
50       if (n&1) mul(ret,a);
51       mul(a,a);
52       n>>=1;
53     }
54 }
55 int main()
56 {
57     n=readl(),mod=readl(); n--;
58     a[1][1]=1; a[1][2]=a[1][3]=0;
59     a[2][1]=a[2][2]=a[2][3]=1;
60     a[3][1]=0; a[3][2]=1; a[3][3]=0;
61     Pow();
62     ans=(ret[1][1]+ret[2][1]+ret[3][1])%mod;
63     out(ans%mod);
64     return 0;
65 }
View Code

 

 #10222. 「一本通 6.5 例 4」佳佳的 Fibonacci

 做法很妙,只不过太弱想不出来。。

设p(n)=n*s(n)-T(n);

因为p(n)=(n-1)*f[1]+(n-2)*f[2]+....

可以推出p(n+1)时每个f(i)前面的系数就要+1,所以p(n+1)=p(n)+s(n).

根据这个递推式就可以愉快地构造了。

要注意的是p(1)=0!

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cmath>
 7 #include <map>
 8 #define ll long long
 9 #define out(a) printf("%lld ",a)
10 #define ln printf("\n")
11 const int N=5;
12 const int MOD=1e9+7;
13 using namespace std;
14 ll n,m;
15 ll mod,ans;
16 ll a[N][N],b[N][N],c[N][N],ret[N][N];
17 int read()
18 {
19     int s=0,t=1; char c=getchar();
20     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
21     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
22     return s*t;
23 }
24 ll readl()
25 {
26     ll s=0,t=1; char c=getchar();
27     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
28     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
29     return s*t;
30 }
31 void mul(ll a[N][N],ll b[N][N])
32 {
33     memset(c,0,sizeof(c));
34     for (int i=1;i<=4;i++)
35       for (int j=1;j<=4;j++){
36         ll sum=0; 
37         for (int k=1;k<=4;k++)
38           sum+=(ll)(a[i][k]*b[k][j])%mod;
39         c[i][j]=sum%mod; 
40       }
41     for (int i=1;i<=4;i++)
42       for (int j=1;j<=4;j++)
43         a[i][j]=c[i][j]; 
44 }
45 void Pow()
46 {
47     for (int i=2;i<=4;i++)
48       ret[i][i]=1;
49     while (n){
50       if (n&1) mul(ret,a);
51       mul(a,a);
52       n>>=1;
53     }
54 }
55 int main()
56 {
57     n=readl(),mod=readl(); m=n; n--; 
58     a[1][1]=1; a[1][2]=a[1][3]=a[1][4]=0;
59     a[2][1]=a[2][2]=1; a[2][3]=a[2][4]=0;
60     a[3][1]=0; a[3][2]=a[3][3]=a[3][4]=1;
61     a[4][1]=a[4][2]=0; a[4][3]=1; a[4][4]=0;
62     Pow();
63     ans=(ret[1][2]+ret[2][2]+ret[3][2]+ret[4][2])*m
64     -(ret[1][1]+ret[2][1]+ret[3][1]+ret[4][1]);
65     out(ans%mod);
66     return 0;
67 }
View Code

 

 

 

posted @ 2019-01-27 09:31  Kaleidoscope233  阅读(179)  评论(0编辑  收藏  举报