POJ3233_Matrix Power Series_矩陣冪_C++


  題目:http://poj.org/problem?id=3233

 

  這是今天考試的題目,結果沒想出來寫了個暴力30分,看完題解之后覺得自己是SB

  

 

  首先暴力就是一個個乘然后相加,時間是O(kn3),極限數據要跑一個月才跑得出來

  我們思考,求冪的話有快速冪(不會快速冪戳這里: http://www.cnblogs.com/hadilo/p/5719139.html ),那么矩陣一樣也是可以的是不是

  因為對於方陣A來說,(A2)2=A4

  於是實數怎樣做快速冪,矩陣就怎樣做

1 while (m>0)
2     {
3         if (m%2) mult(b,a);
4         m/=2;
5         mult(a,a);
6     }

 

  手寫一個 mult 函數,就用最普通的 n3 矩陣乘法

  (矩陣的基本運算,通俗易懂 http://www.cnblogs.com/hadilo/p/5865541.html

 1 void mult(int x[N][N],int y[N][N])
 2 {
 3     int i,j,k;
 4     for (i=1;i<=n;i++)
 5         for (j=1;j<=n;j++)
 6             {
 7                 c[i][j]=0;
 8                 for (k=1;k<=n;k++) c[i][j]=(c[i][j]+x[i][k]*y[k][j])%mo;
 9             }
10     for (i=1;i<=n;i++)
11         for (j=1;j<=n;j++) x[i][j]=c[i][j];
12 }

 

  但題目要求的是 A+A2+...+Ak,而不是單個矩陣的冪

  那么我們可以構造一個分塊的輔助矩陣 S,其中 A 為原矩陣,E 為單位矩陣,O 為0矩陣

  

  我們將 S 取冪,會發現一個特性

  

  Sk 右上角那一塊不正是我們要求的 A+A2+...+A嗎?

  於是我們構造出 S 矩陣,然后對它求矩陣快速冪即可,最后別忘了減去一個單位陣

  時間降為O(n3log2k),從一個月到0.8秒的跨越

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 using namespace std;
 8 
 9 const int N=61;
10 int c[N][N],a[N][N],b[N][N],n,mo;
11 void mult(int x[N][N],int y[N][N])
12 {
13     int i,j,k;
14     for (i=1;i<=n;i++)
15         for (j=1;j<=n;j++)
16             {
17                 c[i][j]=0;
18                 for (k=1;k<=n;k++) c[i][j]=(c[i][j]+x[i][k]*y[k][j])%mo;
19             }
20     for (i=1;i<=n;i++)
21         for (j=1;j<=n;j++) x[i][j]=c[i][j];
22 }
23 int main()
24 {
25     int m,i,j;
26     scanf("%d%d%d",&n,&m,&mo);
27     for (i=1;i<=n;i++)
28         {
29             for (j=1;j<=n;j++) scanf("%d",&a[i][j]);
30             a[i][i+n]=a[i+n][i+n]=b[i][i]=b[i+n][i+n]=1;
31         }
32     n*=2;
33     m++;
34     while (m>0)
35         {
36             if (m%2) mult(b,a);
37             m/=2;
38             mult(a,a);
39         }
40     n/=2;
41     for (i=1;i<=n;i++) b[i][i+n]--;
42     for (i=1;i<=n;i++)
43         {
44             for (j=1;j<n;j++) printf("%d ",b[i][j+n]);
45             printf("%d\n",b[i][j+n]);
46         }
47     return 0;
48 }

 

 

 

版權所有,轉載請聯系作者,違者必究

QQ:740929894


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM