poj3233(矩阵快速幂)

poj3233 http://poj.org/problem?id=3233

给定n ,k,m

然后是n*n行,

我们先可以把式子转化为递推的,然后就可以用矩阵来加速计算了。  矩阵是加速递推计算的一个好工具

我们可以看到,矩阵的每个元素都是一个矩阵,其实这计算一个分块矩阵,我们可以把分块矩阵展开,它的乘法和普通矩阵的乘法是一样的。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <algorithm>
  5 #include <iostream>
  6 #include <queue>
  7 #include <stack>
  8 #include <vector>
  9 #include <map>
 10 #include <set>
 11 #include <string>
 12 #include <math.h>
 13 using namespace std;
 14 #pragma warning(disable:4996)
 15 typedef long long LL;
 16 const int INF = 1 << 30;
 17 int MOD;
 18 /*
 19 矩阵的元素是矩阵,即分块矩阵
 20 分块矩阵的乘法和普通矩阵的乘法是一样的
 21 */
 22 struct Matrix
 23 {
 24     int mat[66][66];
 25     int size;
 26     Matrix(int n)
 27     {
 28         size = n;
 29     }
 30     void makeZero()
 31     {
 32         for (int i = 0; i < size; ++i)
 33         {
 34             for (int j = 0; j < size; ++j)
 35                 mat[i][j] = 0;
 36         }
 37     }
 38     void makeUnit()
 39     {
 40         for (int i = 0; i < size; ++i)
 41         {
 42             for (int j = 0; j < size; ++j)
 43                 mat[i][j] = (i == j);
 44         }
 45     }
 46 };
 47 
 48 Matrix operator*(const Matrix &lhs, const Matrix &rhs)
 49 {
 50     Matrix ret(lhs.size);
 51     ret.makeZero();
 52     for (int i = 0; i < lhs.size; ++i)
 53     {
 54         for (int j = 0; j < lhs.size; ++j)
 55         {
 56             for (int k = 0; k < lhs.size; ++k)
 57             {
 58                 ret.mat[i][j] += (lhs.mat[i][k] * rhs.mat[k][j]);
 59                 if (ret.mat[i][j] >= MOD)
 60                     ret.mat[i][j] %= MOD;
 61             }
 62         }
 63     }
 64     return ret;
 65 }
 66 Matrix operator^(Matrix &a, int k)
 67 {
 68     Matrix ret(a.size);//单位矩阵
 69     ret.makeUnit();
 70     while (k)
 71     {
 72         if (k & 1)
 73         {
 74             ret = ret * a;
 75         }
 76         a = a * a;
 77         k >>= 1;
 78     }
 79     return ret;
 80 }
 81 int main()
 82 {
 83     int n, k, m, i, j;
 84     while (scanf("%d%d%d", &n, &k, &MOD) != EOF)
 85     {
 86         Matrix a(2*n);
 87         Matrix tmp(2*n);;
 88         a.makeZero();
 89         for (i = 0; i < n; ++i)
 90         {
 91             for (j = 0; j < n; ++j)
 92             {
 93                 scanf("%d", &a.mat[i][j]);
 94                 if (a.mat[i][j] >= MOD)
 95                     a.mat[i][j] %= MOD;
 96                 tmp.mat[i][j] = a.mat[i][j];
 97                 tmp.mat[i][n + j] = a.mat[i][j];
 98             }
 99             a.mat[n + i][i] = a.mat[n + i][n + i] = 1;
100         }
101         a = a ^ (k - 1);
102         Matrix ans(2*n);
103         ans.makeZero();
104         m = 2 * n;
105         for (i = 0; i < n; ++i)
106         {
107             for (j = 0; j < n; ++j)
108             {
109                 for (k = 0; k < m; ++k)
110                 {
111                     ans.mat[i][j] += tmp.mat[i][k] * a.mat[k][j];
112                     if (ans.mat[i][j] >= MOD)
113                         ans.mat[i][j] %= MOD;
114                 }
115             }
116         }
117         for (i = 0; i < n; ++i)
118         {
119             for (j = 0; j < n; ++j)
120             {
121                 j == n - 1 ? printf("%d\n", ans.mat[i][j]) : printf("%d ", ans.mat[i][j]);
122             }
123         }
124     }
125     return 0;
126 }
View Code

 

当然了,我们还可以用二分的方法方法来计算

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <algorithm>
  5 #include <iostream>
  6 #include <queue>
  7 #include <stack>
  8 #include <vector>
  9 #include <map>
 10 #include <set>
 11 #include <string>
 12 #include <math.h>
 13 using namespace std;
 14 #pragma warning(disable:4996)
 15 typedef long long LL;
 16 const int INF = 1 << 30;
 17 int MOD;
 18 /*
 19 矩阵的元素是矩阵,即分块矩阵
 20 分块矩阵的乘法和普通矩阵的乘法是一样的
 21 */
 22 struct Matrix
 23 {
 24     int mat[66][66];
 25     int size;
 26     Matrix(int n)
 27     {
 28         size = n;
 29     }
 30     void makeZero()
 31     {
 32         for (int i = 0; i < size; ++i)
 33         {
 34             for (int j = 0; j < size; ++j)
 35                 mat[i][j] = 0;
 36         }
 37     }
 38     void makeUnit()
 39     {
 40         for (int i = 0; i < size; ++i)
 41         {
 42             for (int j = 0; j < size; ++j)
 43                 mat[i][j] = (i == j);
 44         }
 45     }
 46 };
 47 
 48 Matrix operator*(const Matrix &lhs, const Matrix &rhs)
 49 {
 50     Matrix ret(lhs.size);
 51     ret.makeZero();
 52     for (int i = 0; i < lhs.size; ++i)
 53     {
 54         for (int j = 0; j < lhs.size; ++j)
 55         {
 56             for (int k = 0; k < lhs.size; ++k)
 57             {
 58                 ret.mat[i][j] += (lhs.mat[i][k] * rhs.mat[k][j]);
 59                 if (ret.mat[i][j] >= MOD)
 60                     ret.mat[i][j] %= MOD;
 61             }
 62         }
 63     }
 64     return ret;
 65 }
 66 Matrix operator^(Matrix &a, int k)
 67 {
 68     Matrix ret(a.size);//单位矩阵
 69     ret.makeUnit();
 70     while (k)
 71     {
 72         if (k & 1)
 73         {
 74             ret = ret * a;
 75         }
 76         a = a * a;
 77         k >>= 1;
 78     }
 79     return ret;
 80 }
 81 Matrix operator+(const Matrix &lhs, const Matrix &rhs)
 82 {
 83     Matrix ret(lhs.size);
 84     ret.makeZero();
 85     for (int i = 0; i < lhs.size; ++i)
 86     {
 87         for (int j = 0; j < lhs.size; ++j)
 88         {
 89             ret.mat[i][j] = lhs.mat[i][j] + rhs.mat[i][j];
 90             if (ret.mat[i][j] >= MOD)
 91                 ret.mat[i][j] %= MOD;
 92         }
 93     }
 94     return ret;
 95 }
 96 Matrix matrixSum(Matrix a, int k)
 97 {
 98     if (k == 1)
 99         return a;
100     Matrix ret = matrixSum(a, k / 2);
101     if (k & 1)
102     {
103         Matrix tmp = a ^ (k / 2 + 1);
104         ret = ret * tmp + ret + tmp;
105     }
106     else
107     {
108         Matrix tmp = a ^ (k / 2);
109         ret = ret*tmp + ret;
110     }
111     return ret;
112 }
113 int main()
114 {
115     int n, k, m, i, j;
116     while (scanf("%d%d%d", &n, &k, &MOD) != EOF)
117     {
118         Matrix a(n);
119         for (i = 0; i < n; ++i)
120         {
121             for (j = 0; j < n; ++j)
122             {
123                 scanf("%d", &a.mat[i][j]);
124                 if (a.mat[i][j] >= MOD)
125                     a.mat[i][j] %= MOD;
126             }
127         }
128         Matrix ans = matrixSum(a, k);
129         for (i = 0; i < n; ++i)
130         {
131             for (j = 0; j < n; ++j)
132                 j == n - 1 ? printf("%d\n", ans.mat[i][j]) : printf("%d ", ans.mat[i][j]);
133         }
134         return 0;
135     }
136 }
View Code

 

posted @ 2015-04-22 20:57  justPassBy  阅读(418)  评论(0编辑  收藏  举报