矩阵

矩阵快速幂

穿精又带淫゛_ 提交于 2020-02-07 18:20:10
在一些递推n很大的时候,很可能会超时,这样矩阵快速幂就派上用场了. 下面看一个非常经典的例题,斐波那契数列 已知f[1]=1,f[2]=1;F[n]=f[n-1]+f[n-2],给定n,求f[n]; 一看到这到题很多人就会说这不是到入门题吗?;直接上代码 #include<cstdio> #include<cstdlib> #include<iostream> using namespace std; int main() { long long n,a,b; scanf("%lld",&n); a=1,b=1; for(int i=3; i<=n; i++) b=a+b,a=b-a; printf("%lld",b); return 0; } 但是这样很明显是初学者的想的.如果n大一点你呢?这样子这个算法就有点显得太垃圾了.所以我们应该另一种更优的算法.那么这个算法是什么呢?这就要用的了矩阵快速幂了.那么什么是矩阵快速幂呢?在介绍快速幂之前,有几个前置技能 学过oi 会打程序 快速幂 矩阵乘法 前面两个默认你已经掌握了,如果没有,请按Alt + F4 即可; 首先讲一讲快速幂: 什么是快速幂呢?快速幂顾名思义就是快速求幂.其时间复杂度为 O(log₂N), 与朴素的O(N)相比效率有了极大的提高. 如果不想学可以用朴素算法,但是超时就不管了 快速幂算法的详解: 传送门

矩阵快速幂模板+常用变式

╄→гoц情女王★ 提交于 2020-02-07 18:17:03
矩阵乘法(矩阵乘矩阵) 在向量乘向量的运算中,是将每个元素与它对应的元素相乘,求所有乘积之和 那么矩阵乘矩阵是不是就是两个同型矩阵的对应元素相乘呢? 图样图森破 两个矩阵相乘的前提是前一个矩阵的列数等于后一个矩阵的行数 举个栗子,AAA为n∗kn*kn∗k矩阵,BBB为k∗mk*mk∗m矩阵,CCC为m∗nm*nm∗n矩阵,那么AAA可以与BBB相乘,BBB可以与CCC相乘,CCC可以与AAA相乘,其他均不成立 我们知道了什么情况下两个矩阵可以相乘,那么他们怎么相乘呢?不讲每个对应位置相乘还能怎么乘呢? 设AAA为n∗kn*kn∗k矩阵,BBB为k∗mk*mk∗m矩阵,那么它们的乘积CCC则为一个n∗mn*mn∗m矩阵 Ci,j=∑r=1kAi,r∗Br,jC_{i,j}=\sum_{r=1}^kA_{i,r}*B_{r,j}Ci,j​=∑r=1k​Ai,r​∗Br,j​ 是不是不太好理解,没关系看看图就知道了 在矩阵乘法中满足以下运算律: (AB)C=a(BC)(AB)C=a(BC)(AB)C=a(BC) (A+B)C=AC+BC(A+B)C=AC+BC(A+B)C=AC+BC C(A+B)=CA+CBC(A+B)=CA+CBC(A+B)=CA+CB 了解了这么多,我们开始看题,矩阵快速幂,由于矩阵乘法满足结合律,所以我们只需要把它按照一般的快速幂打,再重载一下运算符就可以了

矩阵快速幂

会有一股神秘感。 提交于 2020-02-07 18:13:49
这周学习了矩阵快速幂,就在这里记录下我的一下理解吧。 要学习矩阵快速幂,首先得先知道“矩阵”和“快速幂”的写法。 先说快速幂 顾名思义,快速幂就是快速算底数的n次幂。其时间复杂度为O(log₂N),与朴素的O(N)相比效率有了极大的提高。 ——百度百科 以NOIP2013的麦森数为例题,讲一下快速幂 从文件中输入P(1000<P<3100000),计算2^P-1的位数和最后500位数字(用十进制高精度数表示) 本题显然要使用高精度运算。对2^P-1位数可以用公式log10(2^P-1)+1来求。因为2^P最后一位不可能为0,所以原式可化简为log10(2^P)+1=P*log10(2)+1。于是就能快速得到麦森数的位数了。 我们主要看求最后500位的运算。这显然要用到高精度。但是使用普通的高精度运算,时间复杂度就为P*500^2=2500P。对于最大的P=3100000,显然超时。那有没有更快的算法呢? 这就要牵扯到二进制了,二进制一直是很神奇的一个东西。 以十进制数5举例子,5的二进制为101,这可以通过取模然后反过来得到。看一下101是怎样表示5的。 二进制逢二进一。所以十位上的数就表示这个数有几个2,这就像十进制的十位表示这个数有几个10一样。所以像十进制一样往上推,百位上的数就表示这个数有几个2^2,千位上的数就表示这个数有几个2^3……那么根据这样,就可以看出,101=1

矩阵快速幂小结

旧街凉风 提交于 2020-02-07 18:07:34
update in 9.17 矩阵 并不想扯什么高端线代的内容 因为我也不会 定义 由$n \times m$个数$a_{ij}$排成的$n$行$m$列的数表称为$n$行$m$列的矩阵,简称$n \times m$矩阵。 $$ A = \begin{bmatrix} a_{11} & a_{12} & \dots a_{1m} \\ a_{21}, & \dots & \dots \\ a_{31}, & \dots & \dots \\ a_{41} & \dots & a_{nm} \end{bmatrix} $$ 运算 这里只讲加法减法和乘法,其他的例如矩阵求逆等与本文内容出入较大,有兴趣的可以自己学习 加法 注意,只有行列均相同的矩阵才有加法! 运算也比较简单,把对应位置的数相加得到一个新的矩阵,即为答案 例如 $$ \begin{bmatrix} 1 & 1 & 2 \\ 1 & 0 & 1 \end{bmatrix} + \begin{bmatrix} 2 & 3 & 3 \\ 3 & 3 & 2 \end{bmatrix} = \begin{bmatrix} 3 & 4 & 5 \\ 4 & 3 & 3 \end{bmatrix} $$ 加法满足以下运算律 $A + B = B + A$ $(A + B) + C = A + (B + C)$ 减法 与加法同理。 乘法

浅谈python的第三方库——pandas(一)

蓝咒 提交于 2020-02-07 13:19:13
pandas作为python进行数据分析的常用第三方库,它是基于numpy创建的,使得运用numpy的程序也能更好地使用pandas。 1 pandas数据结构 1.1 Series 注:由于pandas与numpy关系密切,所以在代码中经常将二者一同导入使用。 上图中,先利用numpy创建一个一维数组,再利用pandas的内置方法将其转换为pandas的序列类型Series。可以看到,pandas会自动将原有数据转换成一列,并添加行的索引。 1.2 DataFrame pandas的第二种也是最具代表性的数据结构就是DataFrame。 显然,DataFrame就是矩阵类型的数据,只不过pandas中会给矩阵添加行列索引,以便使用与查找元素。 2 创建DataFrame 由于Series可以视为DataFrame的一种简单情况,所以后面将主要介绍DataFrame,关于Series的情况可以类比过去。 从前一小节可以看到,pandas的数据可以通过运用内置方法转换numpy创建的数据得到,但也可以直接在pandas库内创建DataFrame。 创建DataFrame时,可以手动给数据添加行列名,否则pandas会自动添加形如“0,1,2,3”的行列名。 由于pandas基于numpy制作,所以numpy中的一些常用方法可以直接移植过来。

第二讲 cs224n系列之word2vec & 词向量

*爱你&永不变心* 提交于 2020-02-07 09:48:47
本系列是一个基于深度学习的NLP教程,2016年之前叫做CS224d: Deep Learning for Natural Language Processing,之后改名为CS224n: Natural Language Processing with Deep Learning。新版主讲人是泰斗Chris Manning和Richard Socher(这是旧版的讲师),两人分别负责不同的章节。博主在学习的同时,对重点内容做成系列教程,与大家分享! 系列目录(系列更新中) 第二讲 cs224n系列之word2vec & 词向量 1.语言模型 神经概率语言模型(Neural Probabilistic Language Model)中词的表示是向量形式、面向语义的。两个语义相似的词对应的向量也是相似的,具体反映在夹角或距离上。甚至一些语义相似的二元词组中的词语对应的向量做线性减法之后得到的向量依然是相似的。词的向量表示可以显著提高传统NLP任务的性能,例如《基于神经网络的高性能依存句法分析器》中介绍的词、词性、依存关系的向量化对正确率的提升等。 2.word2vec word2vec是一个计算word vector的开源工具。当我们在说word2vec算法或模型的时候,其实指的是其背后用于计算word vector的CBoW模型和Skip-gram模型

搜索二维矩阵 II

烈酒焚心 提交于 2020-02-07 08:53:36
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性: 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 示例: 现有矩阵 matrix 如下: [ [1, 4, 7, 11, 15], [2, 5, 8, 12, 19], [3, 6, 9, 16, 22], [10, 13, 14, 17, 24], [18, 21, 23, 26, 30] ] 给定 target = 5 ,返回 true 。 给定 target = 20 ,返回 false 。 分析: 1. 暴力搜索O(m*n) 2. 注意观察左下角和右上角的数字,以左下角为例,上面的数字都小于它,右面的数字都大于它,那么,如果target大于它就往右边搜索,小于它就往左边搜索,知道找到或者数组越界,使用递归完成。 class Solution { public: bool searchMatrix(vector<vector<int>>& matrix, int target) { // 左下角的数字,往上比它小,往右比它大,可以递归完成寻找 // 从右上角开始也可以 if(matrix.size() == 0) return false; // 横纵坐标 int x = matrix.size()-1; int y = 0; return find

566 LeetCode重塑矩阵 及vector存放vector的书写

一曲冷凌霜 提交于 2020-02-07 08:13:00
题目描述: 思路:重新构造矩阵,即重新赋值; 首先,把原矩阵里面里面所有值都放在一个vector里面(以便后面使用); 然后,判断将要构造的矩阵的大小与原矩阵的大小; 最后,如果能构造新矩阵,就按照给定的行与列重新赋值; 代码如下: class Solution { public : vector < vector < int >> matrixReshape ( vector < vector < int >> & nums , int r , int c ) { vector < vector < int >> res ( r , vector < int > ( c ) ) ; vector < int > n ; for ( int i = 0 ; i < nums . size ( ) ; i ++ ) { for ( int j = 0 ; j < nums [ i ] . size ( ) ; j ++ ) { n . push_back ( nums [ i ] [ j ] ) ; } } if ( r * c != n . size ( ) ) return nums ; int k = 0 ; for ( int i = 0 ; i < r ; i ++ ) { int j = 0 ; while ( j < c && k < n . size ( ) ) {

二维数组的内存映像

半世苍凉 提交于 2020-02-07 06:49:34
6.3.3 二维数组在形式上很像一个矩阵或者一个二维的表格,例如: int a[2][3]; 可以把二维数组a的所有元素放在一个二维表中: a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] 二维数组在定义后,同样系统会为它申请内存。如果是一个m*n的二维数组,需要申请m*n的内存单元,每个内存单元所需的字节数取决于二维数组的类型。例如上述的二维数组a,因为int型变量占用2个字节(Turbo C环境),那么a数组需要2*3*2=12个字节的内存。 C语言规定:二维数组元素在内存中顺序排放,排列顺序是按行存放。即先顺序存放第一行的数组元素,然后存放第二行的数组元素,依此类推。 上述的二维数组a在内存中映像为(假设系统为a分配内存的首地址为2C80): C语言中还可以使用超过2维的多维数组。例如可以定义一个三维的数组: int a[2][3][4]; 多维数组元素在内存中的排列规则是:最左面的下标变化的最慢,最右面的下标变化的最快。上述三维数组a的数组元素排列顺序是: a[0][0][0]=>a[0][0][1]=> a[0][0][2]=> a[0][0][3]=> a[0][1][0]=> a[0][1][1]=> a[0][1][2]=> a[0][1][3]=> a[0][2][0]=> a[0][2][1]=> a[0][2][2

C++二维数组动态申请内存

谁都会走 提交于 2020-02-07 05:05:17
好久没用C++刷题了,今天早上刷了几条题,感觉很陌生了。怪我,大二下实在太颓废了,没啥作为。 今天更新个关于c++二维数组内存申请的问题,当初作为菜鸟初学指针的时候,还是在这方面有点搞不通的。今天用到了,顺便写下来,适当时候给C++初学者用用。 -----------C++二维数组动态申请内存-------------- 如果对new和delete不是很了解的话可以到这里来看看,http://www.cnblogs.com/hazir/p/new_and_delete.html 首先,我们一般需要用到数组的时候,都是直接声明,比如: 1 int array[3][3]; 但是,在某些情况下,数组的维数我们是不知道的,可能是等待用户输入维数,这时候需要用变量来指定维数了。可是,我们不能直接这样声明数组,因为C++不允许直接用变量作为维数声明,必须用常量,像这样就会报编译错误: 这时候就需要用new来动态申请数组了。我们一步一步来,申请一维数组的时候,我们可以这样写: int num = 3; int* array = new int[num]; 这段代码的意思就是,用new来申请num个int类型的空间,然后返回那段空间的首地址,再赋给array。可见array是一个int类型的指针,指向那段空间的首地址。语法和逻辑无误,正常运行。 但是,申请二维数组的时候