矩阵快速幂及应用实战[C/C++]

矩阵快速幂

矩阵快速幂可以用来优化递推问题,如状态机DP,需要一丢丢线性代数里面矩阵的概念,只需要知道简单的矩阵乘法,结合我们普通的二分快速幂就能很快的掌握矩阵快速幂。

问题引入

三步问题。有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶或3阶。实现一种方法,计算小孩有多少种上楼梯的方式。结果可能很大,你需要对结果模1000000007。

对于这种递推入门题目,相信只要对于编程有着一定了解的人都能够很快的解决掉。

假如我们用传统递推
f ( 0 ) = 1 , f ( 1 ) = 1 , f ( 2 ) = 2 f ( n ) = f ( n − 1 ) + f ( n − 2 ) + f ( n − 3 ) \begin{array}{c} f(0) = 1 , f(1) = 1 , f(2) = 2\\ f(n) = f(n-1) + f(n - 2) + f(n - 3) \end{array} f(0)=1,f(1)=1,f(2)=2f(n)=f(n1)+f(n2)+f(n3)

const int MOD = 1e9 + 7;
int dp[1000001];int waysToStep(int n) {memset(dp , 0 , sizeof(dp));dp[0] = 1, dp[1] = 1 , dp[2] = 2;for(int i = 3 ; i <= n ; i++)dp[i] = ((long long)dp[i - 3] + dp[i - 2] + dp[i - 1]) % MOD;return dp[n];}

时间复杂度:O(N) 空间复杂度:O(N)

因为每次状态都由前三个状态转移过来,如果用滚动数组优化

const int MOD = 1e9 + 7;int waysToStep(int n) {int dp0 = 1, dp1 = 1 , dp2 = 2;if(n <= 1) return 1;if(n == 2) return 2;for(int i = 3 ; i <= n ; i++){int newdp = ((long long)dp0 + dp1 + dp2) % MOD;dp0 = dp1 , dp1 = dp2 , dp2 = newdp;}return dp2;}

空间复杂度优化到了O(1),时间复杂度仍为O(N)

到滚动数组优化这一步对于大多数初学者来说已经很不错了,如果我们想更进一步呢?

我们重新分析递推公式
f ( 0 ) = 1 , f ( 1 ) = 1 , f ( 2 ) = 2 f ( n ) = f ( n − 1 ) + f ( n − 2 ) + f ( n − 3 ) \begin{array}{c} f(0) = 1 , f(1) = 1 , f(2) = 2\\ f(n) = f(n-1) + f(n - 2) + f(n - 3) \end{array} f(0)=1,f(1)=1,f(2)=2f(n)=f(n1)+f(n2)+f(n3)

递推公式到向量计算

第一步

我们尝试把递推公式写成矩阵乘上一个列向量的形式,如下:

( f ( n ) ? ? ) = ( 1 1 1 ? ? ? ? ? ? ) ( f ( n − 1 ) f ( n − 2 ) f ( n − 3 ) ) \begin{pmatrix} f(n)\\ ?\\ ? \end{pmatrix} =\begin{pmatrix} 1 & 1 & 1 \\ ? & ? & ? \\ ? & ? & ? \end{pmatrix} \begin{pmatrix} f(n - 1)\\ f(n - 2) \\ f(n - 3) \end{pmatrix} f(n)?? = 1??1??1?? f(n1)f(n2)f(n3)

第二步

接着尝试填充?部分

( f ( n ) f ( n − 1 ) f ( n − 2 ) ) = ( 1 1 1 ? ? ? ? ? ? ) ( f ( n − 1 ) f ( n − 2 ) f ( n − 3 ) ) \begin{pmatrix} f(n)\\ f(n - 1)\\ f(n - 2) \end{pmatrix} =\begin{pmatrix} 1 & 1 & 1 \\ ? & ? & ? \\ ? & ? & ? \end{pmatrix} \begin{pmatrix} f(n - 1)\\ f(n - 2) \\ f(n - 3) \end{pmatrix} f(n)f(n1)f(n2) = 1??1??1?? f(n1)f(n2)f(n3)

第三步

补充矩阵中的部分,就得到了:

( f ( n ) f ( n − 1 ) f ( n − 2 ) ) = ( 1 1 1 1 0 0 0 1 0 ) ( f ( n − 1 ) f ( n − 2 ) f ( n − 3 ) ) \begin{pmatrix} f(n)\\ f(n - 1)\\ f(n - 2) \end{pmatrix} =\begin{pmatrix} 1 & 1 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \end{pmatrix} \begin{pmatrix} f(n - 1)\\ f(n - 2) \\ f(n - 3) \end{pmatrix} f(n)f(n1)f(n2) = 110101100 f(n1)f(n2)f(n3)

第四步

你以为到这里就结束了?我们在该式子的基础上带入n - 1作为变量,则有:

( f ( n − 1 ) f ( n − 2 ) f ( n − 3 ) ) = ( 1 1 1 1 0 0 0 1 0 ) ( f ( n − 2 ) f ( n − 3 ) f ( n − 4 ) ) \begin{pmatrix} f(n - 1)\\ f(n - 2)\\ f(n - 3) \end{pmatrix} =\begin{pmatrix} 1 & 1 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \end{pmatrix} \begin{pmatrix} f(n - 2)\\ f(n - 3) \\ f(n - 4) \end{pmatrix} f(n1)f(n2)f(n3) = 110101100 f(n2)f(n3)f(n4)

第五步

我们把第四步中的式子带入到第三步中,就会得到

( f ( n ) f ( n − 1 ) f ( n − 2 ) ) = ( 1 1 1 1 0 0 0 1 0 ) ( 1 1 1 1 0 0 0 1 0 ) ( f ( n − 2 ) f ( n − 3 ) f ( n − 4 ) ) \begin{pmatrix} f(n)\\ f(n - 1)\\ f(n - 2) \end{pmatrix} =\begin{pmatrix} 1 & 1 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \end{pmatrix} \begin{pmatrix} 1 & 1 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \end{pmatrix} \begin{pmatrix} f(n - 2)\\ f(n - 3) \\ f(n - 4) \end{pmatrix} f(n)f(n1)f(n2) = 110101100 110101100 f(n2)f(n3)f(n4)

第六步

我们不断地迭代下去就会有这样一个式子:

( f ( n ) f ( n − 1 ) f ( n − 2 ) ) = ( 1 1 1 1 0 0 0 1 0 ) n − 2 ( f ( 2 ) f ( 1 ) f ( 0 ) ) \begin{pmatrix} f(n)\\ f(n - 1)\\ f(n - 2) \end{pmatrix} =\begin{pmatrix} 1 & 1 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \end{pmatrix}^{n-2} \begin{pmatrix} f(2)\\ f(1) \\ f(0) \end{pmatrix} f(n)f(n1)f(n2) = 110101100 n2 f(2)f(1)f(0)
我们发现f(n)的计算还可以通过计算出一个已知矩阵的n - 2次幂与一个列向量的乘积来获取。那么这样的计算方式可以令我们算法的执行效率得到提高吗?

对于两个M阶矩阵做乘积,其时间复杂度为O(M^3),进行n - 2次,那么时间复杂度就是O(M^3 * n),似乎与我们的传统递归相比还要慢上常数阶,于是这就引出了我们今天的主题矩阵快速幂

普通二分快速幂

关于二分快速幂的介绍在笔者的另一篇博客有详细介绍及证明二分快速幂和快读快写模板【C++】-CSDN博客

对于我们快速求a ^ b % p,我们可以不断地二分为(a ^ 2) ^ (b / 2) % p…

如果出现b为奇数,就使得我们最终的返回值ans(ans初始为1)乘上a,当指数为0的时候循环执行完毕,此时ans就是我们的答案。

同样的思想也可以用于矩阵的幂运算中。

代码如下

inline long long quickPower(int a, int b, int p)
{long long ans = 1;while (b){if (b & 1){ans = ans * a % p;}a = a * a % p;b /= 2;}return ans;
}

矩阵二分快速幂

由普通二分快速幂对矩阵做推广,可有如下递归式
A n = { I n = 0 ( A n − 1 2 ) 2 × A n 为奇数 ( A n 2 ) 2 × A n 为非零偶数 A^{n} = \left\{\begin{matrix} I\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ n=0 \\ (A^{\frac{n-1}{2}})^2\times A \ \ \ \ \ \ \ n为奇数 \\ (A^{\frac{n}{2}})^2\times A \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ n为非零偶数 \\ \end{matrix}\right. An= I                     n=0(A2n1)2×A       n为奇数(A2n)2×A                 n为非零偶数
那么我们只需要把普通二分快速幂模板中整数乘法更换成矩阵乘法即可。

矩阵类的定义

struct Matrix
{int m[101][101];Matrix(){memset(m, 0, sizeof(m));}
};

矩阵乘法的运算符重载

Matrix operator*(const Matrix &x, const Matrix &y)
{Matrix ret;for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)for (int k = 1; k <= n; k++)ret.m[i][j] = (ret.m[i][j] + (x.m[i][k] * y.m[k][j]) % MOD) % MOD;return ret;
}

矩阵快速幂模板

Matrix MatrixQuickPower(const Matrix &A, int k)
{Matrix res;for (int i = 1; i <= n; i++)res.m[i][i] = 1; // 单位矩阵while (k){if (k & 1)res = res * A;A = A * A;k >>= 1;}return res;
}

矩阵快速幂就是对普通二分快速幂的基础上,将运算对象更改为了矩阵罢了。

矩阵乘法的常数级优化

我们发现矩阵乘法这里y每次访问m[k][j]寻址需要跳过一整行,对性能其实是有一定影响的,我们可以把第二层循环和第三层循环进行交换

Matrix operator*(const Matrix &x, const Matrix &y)
{Matrix ret;for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)for (int k = 1; k <= n; k++)ret.m[i][j] = (ret.m[i][j] + (x.m[i][k] * y.m[k][j]) % MOD) % MOD;return ret;
}

则有

Matrix operator*(const Matrix &x, const Matrix &y)
{Matrix ret;for (int i = 1; i <= n; i++)for (int k = 1; k <= n; k++)for (int j = 1; j <= n; j++)ret.m[i][j] = (ret.m[i][j] + (x.m[i][k] * y.m[k][j]) % MOD) % MOD;return ret;
}

这样既不影响结果,又降低了寻址消耗。

矩阵快速幂在状态机DP中的应用

如果你学习过数字逻辑电路,相信对于时序电路中的有限状态机不会陌生,没有学过也没有关系,因为学了也不会状态机DP,做算法题早晚都要面对的

其实虽然状态机DP在动态规划中算是一类难度不低的问题,但是只要多做几道题就会很快的掌握其套路,相较于背包问题,难度低了不少,因为套路更容易掌握。

下面详解一道题,留下另一道题供读者练手。

OJ题目精讲

935. 骑士拨号器

象棋骑士有一个独特的移动方式,它可以垂直移动两个方格,水平移动一个方格,或者水平移动两个方格,垂直移动一个方格(两者都形成一个 L 的形状)。

象棋骑士可能的移动方式如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们有一个象棋骑士和一个电话垫,如下所示,骑士只能站在一个数字单元格上(即蓝色单元格)。

img

给定一个整数 n,返回我们可以拨多少个长度为 n 的不同电话号码。

你可以将骑士放置在任何数字单元格上,然后你应该执行 n - 1 次移动来获得长度为 n 的号码。所有的跳跃应该是有效的骑士跳跃。

因为答案可能很大,所以输出答案模 109 + 7.

对于长度为n的电话号码,每个位置有10种情况,如果没有题目中的限制,我们通过简单的组合数学就可以解决.

但现在每个位置可以移动的方式都给出了限制,也就是说在每个位置可以抵达的下一个位置是确定且有限的.

我们如果把每个位置都看做成是一种状态,那么我们有如下的状态转移关系:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们定义状态dp[i][j]为第i次移动后在位置j的情况数,那么我们有如下状态转移方程:
d p [ i ] [ j ] = ∑ d p [ i − 1 ] [ k ] , 其中 j 可由 k 转移 dp[i][j] = \sum dp[i-1][k],其中j可由k转移 dp[i][j]=dp[i1][k],其中j可由k转移

非矩阵快速幂解法

我们打表列出每个位置的的前驱状态,然后执行状态转移方程,最后对dp[n][i]进行累加即可

class Solution {
public:
const int MOD = 1e9 + 7;
vector<vector<int>> pre{{4 , 6} , {6 , 8} , {7 , 9} , {4 , 8} , {0 , 3 , 9} , {} , {0 , 1 , 7} , {2 , 6} , {1 , 3} , {2 , 4}
};int knightDialer(int n) {vector<vector<int>> dp(n + 1 , vector<int>(10));for(int i = 0 ; i < 10 ; i++)dp[1][i] = 1;for(int i = 2 ; i <= n ; i++){for(int j = 0 ; j < 10 ; j++){for(auto x : pre[j])dp[i][j] = (dp[i - 1][x] + dp[i][j]) % MOD; }}long long ret = 0;for(int i = 0 ; i < 10 ; i++)ret = (ret + dp[n][i]) % MOD;return ret;}
};
滚动数组优化

由于每个状态只与上一次状态有关,所以我们还可以优化二维为一维,代码如下:

class Solution {
public:
const int MOD = 1e9 + 7;
vector<vector<int>> pre{{4 , 6} , {6 , 8} , {7 , 9} , {4 , 8} , {0 , 3 , 9} , {} , {0 , 1 , 7} , {2 , 6} , {1 , 3} , {2 , 4}
};int knightDialer(int n) {vector<int> dp(10);for(int i = 0 ; i < 10 ; i++)dp[i] = 1;for(int i = 2 ; i <= n ; i++){vector<int> newdp(10);for(int j = 0 ; j < 10 ; j++){for(auto x : pre[j])newdp[j] = (dp[x] + newdp[j]) % MOD; }dp = newdp;}long long ret = 0;for(int i = 0 ; i < 10 ; i++)ret = (ret + dp[i]) % MOD;return ret;}
};
矩阵快速幂解法

其实我们对于我们矩阵快速幂优化递推问题而言,只要提前写出矩阵A的行列式即可。对于本题我们分析
n e w d p [ 0 ] = d p [ 4 ] + d p [ 6 ] n e w d p [ 1 ] = d p [ 6 ] + d p [ 8 ] n e w d p [ 2 ] = d p [ 7 ] + d p [ 9 ] . . . \begin{array}{c} newdp[0] = dp[4]+dp[6]\\ newdp[1] = dp[6]+dp[8]\\ newdp[2] = dp[7]+dp[9]\\ ... \end{array} newdp[0]=dp[4]+dp[6]newdp[1]=dp[6]+dp[8]newdp[2]=dp[7]+dp[9]...
对于我们的10x10矩阵A的行列式可以很容易的计算出,于是我们的递推公式的矩阵表示为:
$$
\begin{pmatrix}
dpn(0)\
dpn(1)\
dpn(2)\
dpn(3)\
dpn(4)\
dpn(5)\
dpn(6)\
dpn(7)\
dpn(8)\
dpn(9)
\end{pmatrix} =\begin{pmatrix}
{0, 0, 0, 0, 1, 0, 1, 0, 0, 0}\
{0, 0, 0, 0, 0, 0, 1, 0, 1, 0}\
{0, 0, 0, 0, 0, 0, 0, 1, 0, 1}\
{0, 0, 0, 0, 1, 0, 0, 0, 1, 0}\
{1, 0, 0, 1, 0, 0, 0, 0, 0, 1}\
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}\
{1, 1, 0, 0, 0, 0, 0, 1, 0, 0}\
{0, 0, 1, 0, 0, 0, 1, 0, 0, 0}\
{0, 1, 0, 1, 0, 0, 0, 0, 0, 0}\
{0, 0, 1, 0, 1, 0, 0, 0, 0, 0}

\end{pmatrix}^{n} \begin{pmatrix}
dp(0)\
dp(1)\
dp(2)\
dp(3)\
dp(4)\
dp(5)\
dp(6)\
dp(7)\
dp(8)\
dp(9)
\end{pmatrix}
$$
我们矩阵运算时间复杂度为O(103),执行logn次,这样我们的时间复杂度就降到了**O(103 * logn)**

代码如下:

const int MOD = 1e9 + 7;struct Matrix
{long long m[10][10];Matrix(){memset(m, 0, sizeof(m));}Matrix(int x) :m{{0, 0, 0, 0, 1, 0, 1, 0, 0, 0},{0, 0, 0, 0, 0, 0, 1, 0, 1, 0},{0, 0, 0, 0, 0, 0, 0, 1, 0, 1},{0, 0, 0, 0, 1, 0, 0, 0, 1, 0},{1, 0, 0, 1, 0, 0, 0, 0, 0, 1},{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},{1, 1, 0, 0, 0, 0, 0, 1, 0, 0},{0, 0, 1, 0, 0, 0, 1, 0, 0, 0},{0, 1, 0, 1, 0, 0, 0, 0, 0, 0},{0, 0, 1, 0, 1, 0, 0, 0, 0, 0}}{}
};
Matrix A, dp;Matrix operator*(const Matrix& x, const Matrix& y)
{Matrix ret;for (int i = 0; i < 10; i++)for (int k = 0; k < 10; k++)for (int j = 0; j < 10; j++)ret.m[i][j] = (ret.m[i][j] + (x.m[i][k] * y.m[k][j]) % MOD) % MOD;return ret;
}
Matrix MatrixQuickPower(Matrix& A, int k)
{Matrix res;for (int i = 0; i < 10; i++)res.m[i][i] = 1; // 单位矩阵while (k){if (k & 1)res = res * A;A = A * A;k >>= 1;}return res;
}
int init(int n)
{A = Matrix(1);for (int i = 0; i < 10; i++)dp.m[i][0] = 1;Matrix dpn = MatrixQuickPower(A, n - 1) * dp;int ret = 0;for (int i = 0; i < 10; i++)ret = (ret + dpn.m[i][0]) % MOD;return ret;
}
class Solution {
public:int knightDialer(int n) {return init(n);}
};

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

遥遥领先

这里省事直接套模板了,有很多拷贝是可以优化掉的。就不演示了(懒x_x)

练习题OJ链接

这道题留给大家练习

552. 学生出勤记录 II - 力扣(LeetCode)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/182822.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一文学会Aiohttp

一、什么是aiohttp库 aiohttp库官网&#xff1a;https://docs.aiohttp.org/en/stable/ aiohttp是一个Python的HTTP客户端/服务器框架&#xff0c;它基于asyncio库实现异步编程模型&#xff0c;可以支持高性能和高并发的HTTP通信。aiohttp用于编写异步的Web服务器、Web应用程序…

【Vulnhub 靶场】【Coffee Addicts: 1】【简单-中等】【20210520】

1、环境介绍 靶场介绍&#xff1a;https://www.vulnhub.com/entry/coffee-addicts-1,699/ 靶场下载&#xff1a;https://download.vulnhub.com/coffeeaddicts/coffeeaddicts.ova 靶场难度&#xff1a;简单 - 中等 发布日期&#xff1a;2021年5月20日 文件大小&#xff1a;1.3 …

【数值计算方法(黄明游)】常微分方程初值问题的数值积分法:欧拉方法(向后Euler)【理论到程序】

文章目录 一、数值积分法1. 一般步骤2. 数值方法 二、欧拉方法&#xff08;Euler Method&#xff09;1. 向前欧拉法&#xff08;前向欧拉法&#xff09;2. 向后欧拉法&#xff08;后向欧拉法&#xff09;a. 基本理论b. 算法实现 常微分方程初值问题的数值积分法是一种通过数值方…

webpack如何处理文件、图片

webpack5之前是通过&#xff0c;file-loader、raw-loader、url-loader处理文件 webpack5是通过使用资源模块类型&#xff08;asset module type&#xff09;处理文件 资源模块类型(asset module type)&#xff0c;通过添加 4 种新的模块类型&#xff0c;来替换所有这些 loade…

Linux常用命令——rm 命令

文章目录 Linux系统中的rm命令是一个非常强大且危险的工具&#xff0c;用于删除文件和目录。由于其具有不可逆的特性&#xff0c;了解其参数和正确使用非常重要。 1. 基本用法 rm命令的基本格式是rm [选项] 文件或目录。不带任何选项时&#xff0c;rm命令仅删除文件。 示例&a…

python读取excel自动化生成sql建表语句和java实体类字段

1、首先准备一个excel文件&#xff1a; idtypenameidint学号namestring姓名ageint年龄sexstring性别weightdecimal(20,4)体重scoredecimal(20,4)分数 2、直接生成java字段和注释&#xff1a; import pandas as pddf pd.read_excel(test.xlsx, sheet_nameSheet1)for i in ran…

java 对象大小计算

说明&#xff1a; 对于64位机&#xff1a;一个对象由三部分组成 对象头(object header) mark word &#xff1a;64bitkclass pointer &#xff1a;32bit(默认使用指针压缩)&#xff0c;如果取消指针压缩( XX:-UseCompressedOops)&#xff0c;则占用64bit数组长度&#xff1a;数…

Zynq-Linux移植学习笔记之67- 国产ZYNQ上通过GPIO模拟MDC/MDIO协议

1、背景介绍 模块上有9个PHY&#xff0c;其中两个PHY通过ZYNQ PS端的MDIO总线连接&#xff0c;其余7个PHY单独通过GPIO进行控制&#xff0c;需要实现GPIO模拟MDC/MDIO协议。 2、vivado工程设计 vivado工程内为每个PHY建立两个GPIO IP核&#xff0c;分别用来代表MDC和MDIO&…

基于BP神经网络的手写体数字识别matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 filename dir(images\*.bmp); %图像文件格式 load BP.matfilename dir(test\*.bmp); …

PyQt基础_009_ 按钮类控件QSlider

基本功能 import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import *class SliderDemo(QWidget):def __init__(self, parentNone):super(SliderDemo, self).__init__(parent)self.setWindowTitle("QSlider 例子") self.resize…

Google play开发者账号付款资料暂停的原因及解决方案

相信大多数Google play开发者都收到过这封邮件 邮件内容的大致意思是“由于可疑的活动&#xff0c;我们暂停了你的付款资料。” “要恢复您的帐户&#xff0c;请转到您的帐户并执行所要求的操作。” 这是触发了谷歌的付款风控机制&#xff0c;根据开发者们的反馈&#xff0c;账…

滴滴打车崩了!全过程

滴滴发布致歉10元补偿券&#xff0c;文末可领取 。 事情发生于 2023年11月27日晚~28日中午&#xff0c;滴滴打车服务出现大面积故障&#xff0c;登上微博热搜。 许多用户在使用滴滴出行时遇到了无法叫车、订单异常等问题&#xff0c;导致大量用户滞留在外&#xff0c;出行受阻…

2023年11月编程语言排行榜——你的编程语言上榜了吗?

编程语言的流行度是一个热门的话题&#xff0c;不同的机构和平台有不同的评判标准和排名方法。本文将以 TIOBE 编程社区指数为例&#xff0c;介绍 2023 年 11 月的编程语言趋势榜单&#xff0c;分析各种编程语言的表现和原因&#xff0c;以及对未来的展望。 TIOBE 编程社区指数…

【小黑嵌入式系统第二课】嵌入式系统的概述(二)——外围设备、处理器、ARM、操作系统

上一课&#xff1a; 【小黑嵌入式系统第一课】嵌入式系统的概述&#xff08;一&#xff09;——概念、特点、发展、应用 下一课&#xff1a; 【小黑嵌入式系统第三课】嵌入式系统硬件平台&#xff08;一&#xff09;——概述、总线、存储设备&#xff08;RAM&ROM&FLASH…

QDoubleSpinBox的使用示例

QDoubleSpinBox即可以做为数值型输入框使用&#xff0c;也可以使用只读型数据显示框&#xff0c;在作为输入框使用时比QLineEdit有以下几个方面的优势 1.可以设置范围&#xff0c;并且范围精确&#xff0c; 2.输入数据精确&#xff0c;自动屏幕非数值以外的字符。 3.设置步长后…

文件基础知识

计算机中的流&#xff1a;在C语言中将通过输入/输出设备&#xff08;键盘、内存、显示器、网络等&#xff09;之间的数据传输抽象表述为“流”。 1、文本流和二进制流 在文本流中输入输出的数据是一系列的字符&#xff0c;可以被修改在二进制流中输入输出数据是一系列字节&am…

RabbitMQ消息模型之Sample

Hello World Hello World是官网给出的第一个模型&#xff0c;使用的交换机类型是直连direct&#xff0c;也是默认的交换机类型。 在上图的模型中&#xff0c;有以下概念&#xff1a; P&#xff1a;生产者&#xff0c;也就是要发送消息的程序C&#xff1a;消费者&#xff1a;消…

【Linux】gcc和g++

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和Linux还有算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 …

git-4

1.在GitHub上创建个人仓库 现在仓库中有LICENSE文件&#xff0c;但本地没有这个文件&#xff0c;该怎么办呢&#xff1f;往下看 2.把本地仓库同步到GitHub 3.不同人修改了不同文件如何处理&#xff1f; 两个人在同一个分支上&#xff0c;两个人修改了不同文件 其中一人&…

Python 哈希表的实现——字典

哈喽大家好&#xff0c;我是咸鱼 接触过 Python 的小伙伴应该对【字典】这一数据类型都了解吧 虽然 Python 没有显式名称为“哈希表”的内置数据结构&#xff0c;但是字典是哈希表实现的数据结构 在 Python 中&#xff0c;字典的键&#xff08;key&#xff09;被哈希&#x…