zoukankan      html  css  js  c++  java
  • 矩阵乘法

    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("
    ")
    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("
    ")
    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("
    ")
    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("
    ")
    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

     

  • 相关阅读:
    算法:归并排序
    算法:希尔排序
    算法:插入排序
    算法:冒泡排序
    算法:选择排序
    jQuery
    (二)多线程之开启线程的两种方式
    (一)多线程之线程理论
    (四)多进程之队列与生产者消费者模型
    (三)多进程之守护进程与互斥锁
  • 原文地址:https://www.cnblogs.com/Kaleidoscope233/p/10325621.html
Copyright © 2011-2022 走看看