zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", ans.mat[i][j]) : printf("%d ", ans.mat[i][j]);
    133         }
    134         return 0;
    135     }
    136 }
    View Code
  • 相关阅读:
    Vue2 后台管理系统解决方案
    vuejs 和 element 搭建的一个后台管理界面
    Composer 是什么
    解决无限 This file is indented with tabs instead of 4 spaces
    (七)boost库之单例类
    (六)boost库之内存管理shared_ptr
    (五)boost库之随机数random
    (四)boost库之正则表达式regex
    (二)boost库之字符串格式化
    (一)boost库之日期、时间
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4448630.html
Copyright © 2011-2022 走看看