【矩阵快速幂】封装类及测试用例及样例

简介: 【矩阵快速幂】封装类及测试用例及样例

作者推荐

视频算法专题

通俗的说,就是矩阵的乘方。

封装类

核心代码

class CMat
{
public:
  // 矩阵乘法
  static vector<vector<long long>> multiply(const vector<vector<long long>>& a, const vector<vector<long long>>& b) {
    const int r = a.size(), c = b.front().size(),iK = a.front().size();
    assert(iK == b.size());
    vector<vector<long long>> ret(r, vector<long long>(c));
    for (int i = 0; i < r; i++)
    {
      for (int j = 0; j < c ; j++) 
      {
        for (int k = 0; k < iK; k++)
        {
          ret[i][j] = (ret[i][j] + a[i][k] * b[k][j] ) % s_llMod;
        }
      }
    }
    return ret;
  }
  // 矩阵快速幂
  static vector<vector<long long>> pow( const vector<vector<long long>>& a, vector<vector<long long>> b, long long n) {
    vector<vector<long long>> res = a;
    for (; n; n /= 2) {
      if (n % 2) {
        res = multiply(res, b);
      }
      b = multiply(b, b);
    }
    return res;
  }
  static vector<vector<long long>> TotalRow(const vector<vector<long long>>& a)
  {
    vector<vector<long long>> b(a.front().size(), vector<long long>(1, 1));
    return multiply(a, b);
  }
protected:
  const static long long s_llMod = 1e9 + 7;
};

测试用例

template<class T>
void Assert(const T& t1, const T& t2)
{
  assert(t1 == t2);
}
template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
  if (v1.size() != v2.size())
  {
    assert(false);
    return;
  }
  for (int i = 0; i < v1.size(); i++)
  {
    Assert(v1[i], v2[i]);
  }
}
int main()
{
  vector<vector<long long>> pre = { {1,2} };
  vector<vector<long long>> mat = { {2,3},{1,10} };
  { 
    auto res = CMat::pow(pre, mat, 0);
    Assert(pre, res);
  }
  {
    auto res = CMat::multiply(pre, mat);
    Assert(vector<vector<long long>>{ {4, 23}}, res);
    auto res2 = CMat::pow(pre, mat,1);
    Assert(res2, res);
  }
  {
    auto res = CMat::pow(pre, mat, 2);
    auto res1 = CMat::multiply(pre, mat);
    auto res2 = CMat::multiply(res1, mat);
    Assert(res2, res);
    Assert(vector<vector<long long>>{ {31, 242}}, res);
  };
  for (int i = 3; i < 100; i++)
  {
    auto res = pre;
    for (int j = 0; j < i; j++)
    {
      res = CMat::multiply(res, mat);
    }
    auto res2 = CMat::pow(pre, mat, i);
    Assert(res2, res);
  }
  
}

具体例子

题目、分析和原理见:

【动态规划】【矩阵快速幂】【滚动向量】C++算法552. 学生出勤记录 II

原解法用二维表示状态,改成一维。 i是缺勤数量,j是连续迟到数,新的状态为:3*i+j

6种状态,故转移矩阵为6行6列,故结果矩阵为6列,6个数据1行就足够了。

令旧结果矩阵为mat1,转移矩阵为mat2,新矩阵为mat3,K mat1的列数,mat2的行数。则:

mat3[r][c] = Sum[ 0 , k ) i ^{i}_{[0,k)}[0,k)i(mat1[r][i]*mat2[i][c])

i在mat1中列号,在mat2中是行号。 也就是旧状态在第几列,mat2就在第几行。

新状态就是mat2的行号。

class Solution {
public:
  int checkRecord(int n) {
    vector<vector<long long>> pre(1, vector<long long>(6));//1行6列 
    pre[0][0] = 1;
    vector<vector<long long>> mat(6, vector<long long>(6));
    { 
      //之前的状态在pre是第几列,矩阵中就是第几行。新状态的列号就矩阵的列号
      //处理一次缺勤 ,缺勤两次排除
      for (int i = 0; i < 3; i++)
      {
        mat[i][3]++;
      }
      //处理请假
      for (int i = 0; i < 2; i++)
      {
        for (int j = 0; j < 2; j++)
        {
          const int pre = 3 * i + j;
          mat[pre][pre + 1]++;
        }
      }
      //处理正常
      for (int i = 0; i < 2; i++)
      {
        for (int j = 0; j < 3; j++)
        {
          const int pre = 3 * i + j;
          const int cur = 3 * i;
          mat[pre][cur]++;
        }
      }
    }
    auto res = CMat::pow(pre, mat, n);
    res = CMat::TotalRow(res);
    return res[0][0];
  }
};

测试用例

template

void Assert(const T& t1, const T& t2)

{

assert(t1 == t2);

}

template

void Assert(const vector& v1, const vector& v2)

{

if (v1.size() != v2.size())

{

assert(false);

return;

}

for (int i = 0; i < v1.size(); i++)

{

Assert(v1[i], v2[i]);

}

}

int main()

{

int n;

{

Solution sln;

n = 0;

auto res = sln.checkRecord(n);

Assert(1, res);

}

{

Solution sln;

n = 1;

auto res = sln.checkRecord(n);

Assert(3, res);

}

{

Solution sln;

n = 2;

auto res = sln.checkRecord(n);

Assert(8, res);

}

{

Solution sln;

n = 3;

auto res = sln.checkRecord(n);

Assert(19, res);

}

{

Solution sln;

n = 4;

auto res = sln.checkRecord(n);

Assert(43, res);

}

{

Solution sln;

n = 5;

auto res = sln.checkRecord(n);

Assert(94, res);

}

{

Solution sln;

n = 6;

auto res = sln.checkRecord(n);

Assert(200, res);

}

{

Solution sln;

n = 7;

auto res = sln.checkRecord(n);

Assert(418, res);

}

{

Solution sln;

n = 10101;

auto res = sln.checkRecord(n);

Assert(183236316, res);

}

}


相关文章
|
1月前
Mybatis+mysql动态分页查询数据案例——测试类HouseDaoMybatisImplTest)
Mybatis+mysql动态分页查询数据案例——测试类HouseDaoMybatisImplTest)
21 1
|
1月前
|
Java
【Java每日一题】— —第二十一题:编程把现实生活的手机事物映射成一个标准类Phone,并定义一个测试类PhoneDemo测试Phone类的功能
【Java每日一题】— —第二十一题:编程把现实生活的手机事物映射成一个标准类Phone,并定义一个测试类PhoneDemo测试Phone类的功能
36 0
|
1月前
|
Java
java面向对象高级分层实例_测试类(main方法所在的类)
java面向对象高级分层实例_测试类(main方法所在的类)
10 1
|
1月前
|
测试技术 Python
在Python中测试类
在Python中测试类
11 1
|
2月前
|
数据可视化 jenkins 测试技术
可视化BI类产品如何设计测试框架?
可视化BI类产品如何设计测试框架?
|
17天前
|
测试技术 C语言
网站压力测试工具Siege图文详解
网站压力测试工具Siege图文详解
26 0
|
1月前
|
JavaScript jenkins 测试技术
这10款性能测试工具,收藏起来,测试人的工具箱!
这10款性能测试工具,收藏起来,测试人的工具箱!
|
1月前
|
人工智能 监控 测试技术
利用AI辅助工具提升软件测试效率
【2月更文挑战第17天】 随着科技的不断发展,人工智能(AI)在各个领域的应用越来越广泛。在软件测试领域,AI技术也发挥着重要作用。本文将探讨如何利用AI辅助工具提升软件测试效率,包括自动化测试、智能缺陷识别和预测等方面。通过引入AI技术,软件测试过程将变得更加高效、准确和可靠。
195 1
|
1月前
|
Web App开发 前端开发 测试技术
探索自动化测试工具:Selenium的威力与应用
探索自动化测试工具:Selenium的威力与应用
探索自动化测试工具:Selenium的威力与应用
|
1月前
|
测试技术
现代软件测试中的自动化工具与挑战
传统软件测试面临着越来越复杂的系统架构和不断增长的测试需求,自动化测试工具应运而生。本文将探讨现代软件测试中自动化工具的应用和挑战,深入分析其优势与局限性,为软件测试领域的发展提供思路和启示。

热门文章

最新文章