等差数列和特殊矩阵压缩公式/下标计数公式的应用

等差数列和特殊矩阵压缩公式/下标计数公式的应用

ref

等差数列

递推公式

  • a n = a n − 1 + d ; ( n = 2 , 3 , . . . ) a_n=a_{n-1}+d;(n=2,3,...) an=an1+d;(n=2,3,...)
    • 注意,有的时候d是一个负值
  • 此外,由数列的和的定义可知:
    • 对于任何数列 , 总是有 a n = s n − s n − 1 ; ( n = 2 , 3 , . . . ) ; s n 表示前 n 项和 对于任何数列,总是有a_n=s_n-s_{n-1};(n=2,3,...);s_n表示前n项和 对于任何数列,总是有an=snsn1;(n=2,3,...);sn表示前n项和
    • 有时候会很有用,比如在推导排序不等式的时候

通项

  • 相关公式和性质可以有通项公式推导

  • a n = a 1 + ( n − 1 ) d ; n = 1 , 2 , 3 , . . . a n = a 1 + n d − d = d n + ( a 1 − d ) ; ( 将 n 视为变量 ) 那么对于任何 f ( x ) = k x + b , 都可以看做是一个等差数列的通项 d = k ; a 1 − d = b ; ( a 1 = b + d ) a_n=a_1+(n-1)d ;n=1,2,3,... \\ a_n=a_1+nd-d=dn+(a_1-d);(将n视为变量) \\那么对于任何f(x)=kx+b,都可以看做是一个等差数列的通项 \\d=k;a_1-d=b;(a_1=b+d) an=a1+(n1)d;n=1,2,3,...an=a1+ndd=dn+(a1d);(n视为变量)那么对于任何f(x)=kx+b,都可以看做是一个等差数列的通项d=k;a1d=b;(a1=b+d)

  • 相邻项的性质

    • a n = a n − 1 + a n + 1 2 ; n = 2 , 3 , . . . a_n=\frac{a_{n-1}+a_{n+1}}{2};n=2,3,... an=2an1+an+1;n=2,3,...
    • a n + a m = a q + a p ; ( m + n = p + q = t 常数 ) a_n+a_m=a_q+a_p;(m+n=p+q=t常数) an+am=aq+ap;(m+n=p+q=t常数)

等差数列和

  • 由通向公式 a n = a 1 + ( n − 1 ) d a 1 = a 1 + 0 d a 2 = a 1 + d a 3 = a 1 + 2 d . . . a n = a 1 + ( n − 1 ) d s = ∑ i = 1 n a i = ∑ i = 1 n ( a 1 + ( n − 1 ) d ) = a 1 ∑ i = 1 n 1 + d ∑ i = 1 n ( n − 1 ) = n a 1 + d ( n − 1 ) + ( n − 2 ) + . . . + 0 2 = n a 1 + d n ( n − 1 ) 2 \\由通向公式a_n=a_1+(n-1)d \\a_1=a_1+0d \\a_2=a_1+d \\a_3=a_1+2d \\... \\a_n=a_1+(n-1)d \\s=\sum\limits_{i=1}^{n}a_i=\sum\limits_{i=1}^{n}(a_1+(n-1)d) =a_1\sum\limits_{i=1}^{n}1+d\sum\limits_{i=1}^{n}(n-1)\\ =na_1+d\frac{(n-1)+(n-2)+...+0}{2} \\=na_1+d\frac{n(n-1)}{2} 由通向公式an=a1+(n1)da1=a1+0da2=a1+da3=a1+2d...an=a1+(n1)ds=i=1nai=i=1n(a1+(n1)d)=a1i=1n1+di=1n(n1)=na1+d2(n1)+(n2)+...+0=na1+d2n(n1)

    或者
    s = n ( a 1 + a n ) 2 另外 , 对于等差数列 , 如果 x + y = t ; ( t 为常数 ) 那么根据通向公式有 a x + a y = 2 a 1 + ( t − 2 ) d ( 是一个常数 ) 当 t 取 n + 1 时 : a x + a y = 2 a 1 + ( n − 1 ) d 因此 , 有倒序相加是 2 s 可得到 : s = n ( a 1 + a n ) 2 = n ( a x + a n + 1 − x ) 2 s=n\frac{(a_1+a_n)}{2} \\另外,对于等差数列,如果x+y=t;(t为常数) \\那么根据通向公式有a_x+a_y=2a_1+(t-2)d(是一个常数) \\当t取n+1时:a_x+a_y=2a_1+(n-1)d \\因此,有倒序相加是2s可得到:s=n\frac{(a_1+a_n)}{2}=n\frac{(a_x+a_{n+1-x})}{2} s=n2(a1+an)另外,对于等差数列,如果x+y=t;(t为常数)那么根据通向公式有ax+ay=2a1+(t2)d(是一个常数)tn+1:ax+ay=2a1+(n1)d因此,有倒序相加是2s可得到:s=n2(a1+an)=n2(ax+an+1x)

等差求和公式的应用

  • 假设函数 f ( x ) 用表格法可以做如下的描述 ; 其中 i , n 为常数 假设函数f(x)用表格法可以做如下的描述;其中i,n为常数 假设函数f(x)用表格法可以做如下的描述;其中i,n为常数
x x x f ( x ) f(x) f(x)
1 n n n
2 n − 1 n-1 n1
3 3 3 n − 2 n-2 n2
i n − ( i − 1 ) n-(i-1) n(i1)
  • 也就是说 f ( x ) = n − ( x − 1 ) = n + 1 − x 也就是说f(x)=n-(x-1)=n+1-x 也就是说f(x)=n(x1)=n+1x

  • 可以看出 f ( x ) 是一个公差为 d = − 1 的等差数列 可以看出f(x)是一个公差为d=-1的等差数列 可以看出f(x)是一个公差为d=1的等差数列

  • f ( x ) 前 i 项和为 s i = i a 1 + d i ( i − 1 ) 2 = i n + ( − 1 ) i ( i − 1 ) 2 = 1 2 i ( 2 n − i + 1 ) f(x)前i项和为s_i=ia_1+d\frac{i(i-1)}{2}=in+(-1)\frac{i(i-1)}{2}=\frac{1}{2}i(2n-i+1) f(x)i项和为si=ia1+d2i(i1)=in+(1)2i(i1)=21i(2ni+1)

    • 或者 , 如果我们写出了第 i 项的 f ( x ) = n − ( i − 1 ) , s i = 1 2 n ( a 1 + a n ) = 1 2 i ( 2 n − i + 1 ) 或者,如果我们写出了第i项的f(x)=n-(i-1), \\s_i=\frac{1}{2}n(a_1+a_n)=\frac{1}{2}i(2n-i+1) 或者,如果我们写出了第i项的f(x)=n(i1),si=21n(a1+an)=21i(2ni+1)
  • 在上三角矩阵解压缩公式中,上述 i ( i ) = i − 1 i(i)=i-1 i(i)=i1公式取

    • a i , j = B [ k ] , ( i ⩽ j , i 是从 1 开始计数的矩阵行坐标 ) 函数 k ( i , j ) 表示元素 a i , j 被压缩到数组 B 中的那个位置 ( 下标值 ) 而根据压缩算法 , 这个值就是矩阵中 , a i , j 前面的元素个数 k ( i , j ) = 1 2 ( i − 1 ) ( 2 n − i + 2 ) + ( j − i ) a_{i,j}=B[k],(i\leqslant j,i是从1开始计数的矩阵行坐标) \\函数k(i,j)表示元素a_{i,j}被压缩到数组B中的那个位置(下标值) \\而根据压缩算法,这个值就是矩阵中,a_{i,j}前面的元素个数 \\k(i,j)=\frac{1}{2}(i-1)(2n-i+2)+(j-i) ai,j=B[k],(ij,i是从1开始计数的矩阵行坐标)函数k(i,j)表示元素ai,j被压缩到数组B中的那个位置(下标值)而根据压缩算法,这个值就是矩阵中,ai,j前面的元素个数k(i,j)=21(i1)(2ni+2)+(ji)

数列/数组游标计数公式

问题对象

  • 设自然数序列 1 , 2 , 3 , 4 , . . . , p − 1 , p , . . . , n − 1 , n ⏟ 共计 m 个元素 ; 其中 p < n 设自然数序列1,2,3,4,...,p-1,\underset{共计m个元素}{\underbrace{p,...,n-1,n}};其中p<n 设自然数序列1,2,3,4,...,p1,共计m个元素 p,...,n1,n;其中p<n
  • 更一般序列形式: 序列 { a n } = ⋯   , a 1 , a 2 , a 3 , ⋯   , a p , ⋯   , a q , ⋯   ; 序列\{a_n\}=\cdots,a_1,a_2,a_3,\cdots,a_p,\cdots,a_q,\cdots; 序列{an}=,a1,a2,a3,,ap,,aq,;
    • 下标 ( i n d e x i ) 体现了元素间的先后关系和相邻关系 下标(index_i)体现了元素间的先后关系和相邻关系 下标(indexi)体现了元素间的先后关系和相邻关系

问题内容

  • 这是一维序列区间计数公式的相关讨论
    • 主要包括:

    • 知道闭区间两端元素的序号,求区间内包含多少个元素

    • 知道区间长度和区间的一个断点序号(坐标)求另一个端点的序号

  • 尽管看起来讨论这种问题有点幼稚,但是为了提高解题效率,还是值得整理的
问题变体
  • 开区间容易转化为闭区间问题,下面的实例中将会看到

A指针序号差/地址增量偏移/坐标计算offset

  • 这一部分是讨论由区间长度计算另一端坐标的问题

  • 区间&坐标问题本质的表现之一

  • **增量 Δ = e n d − s t a r t \Delta=end-start Δ=endstart**在这个问题上是一个核心概念

    • 为了便于使用,我们也叫做序号差(坐标差)
    • 增量有正负之分
    • 序号沿着增大的方向变化的, 称为正增量 Δ > 0 称为正增量\Delta>0 称为正增量Δ>0
    • 沿着负方向减小的方向变化的, 称为负增量 Δ < 0 称为负增量\Delta<0 称为负增量Δ<0
  • a 1 , a 2 , ⋯   , a n a_1,a_2,\cdots,a_n a1,a2,,an

    • a i a i + 1 ⋯ a j − 1 a j ⏟ 子串长度为 Δ = j − i a_i\underbrace{a_{i+1}\cdots a_{j-1}a_{j}}_{子串长度为\Delta=j-i} ai子串长度为Δ=ji ai+1aj1aj

      • 增量区间内 Δ = j − i 内的元素不包括 a i ; 即 , 仅包括 [ a i + 1 , a j ] 增量区间内\Delta=j-i内的元素不包括a_i;即,仅包括[a_{i+1},a_{j}] 增量区间内Δ=ji内的元素不包括ai;,仅包括[ai+1,aj]

      • 或者 a i a i + 1 ⋯ a j − 1 ⏟ 负增量 Δ = i − j a j \underbrace{a_ia_{i+1}\cdots a_{j-1}}_{负增量\Delta=i-j}a_{j} 负增量Δ=ij aiai+1aj1aj

        • 由于 a i ∼ a j − 1 共有 L 个元素 ; 每数一下 , 序号在 y 的基础上 − 1 元素 : 序号 a j : y a j − 1 : y − 1 a j − 2 : y − 2 ⋮ a i + 1 : y − ( L − 1 ) a i : y − ( L ) 即 x = y − L 由于a_i\sim a_{j-1}共有L个元素;每数一下,序号在y的基础上-1 \\元素:序号 \\a_{j}:y \\a_{j-1}:y-1 \\a_{j-2}:y-2 \\\vdots \\a_{i+1}:y-(L-1) \\a_{i}:y-(L) \\即x=y-L 由于aiaj1共有L个元素;每数一下,序号在y的基础上1元素:序号aj:yaj1:y1aj2:y2ai+1:y(L1)ai:y(L)x=yL

        • 特别的 , 当 L = 1 有 a i a j ⏟ L = 1 特别的,当L=1有a_i\underbrace{a_{j}}_{L=1} 特别的,L=1aiL=1 aj

o f f s e t = L = Δ = j − i ; offset=L=\Delta=j-i; offset=L=Δ=ji;

  • 结合下面的描述, ∣ Δ ∣ = ∣ j − i ∣ |\Delta|=|j-i| ∣Δ∣=ji可以理解为:

    • 元素 [ a i + 1 , a j ] 闭区间内元素数目 ∣ Δ ∣ 元素[a_{i+1},a_{j}]闭区间内元素数目|\Delta| 元素[ai+1,aj]闭区间内元素数目∣Δ∣

    • 或者理解为指针从 a i 移动到 a j 需要执行单步移动次数 或者理解为指针从a_i移动到a_j需要执行单步移动次数 或者理解为指针从ai移动到aj需要执行单步移动次数

    • 设 a i 的序号为 x ; a j 的序号为 y ; 设a_i的序号为x;a_j的序号为y; ai的序号为x;aj的序号为y;

      • 那么 y = x + Δ ; 或者 x = y − Δ 那么y=x+\Delta;或者x=y-\Delta 那么y=x+Δ;或者x=yΔ
      • 特别的 Δ = 1 , y = x + 1 ; x = y − 1 特别的\Delta=1,y=x+1;x=y-1 特别的Δ=1,y=x+1;x=y1
  • ★   a i + Δ = a i + Δ ; 表示指向 a i 的指针经过正方向偏移 L 次 ( 其中每次偏移 , 指针从前一个元素移动到相邻的后一个元素 , 下标 ( 序号 ) 变化 1 ) \bigstar\ a_i+\Delta=a_{i+\Delta}; \\表示指向a_i的指针经过正方向偏移L次 \\(其中每次偏移,指针从前一个元素移动到相邻的后一个元素,下标(序号)变化1)  ai+Δ=ai+Δ;表示指向ai的指针经过正方向偏移L(其中每次偏移,指针从前一个元素移动到相邻的后一个元素,下标(序号)变化1)

    • 例如 , 当 i = 1 , Δ = 1 时 , p 1 经过一次移动变为 p 2 例如,当i=1,\Delta=1时,p_1经过一次移动变为p_2 例如,i=1,Δ=1,p1经过一次移动变为p2

      • a 1 ↑ p 1 , a 2 ↑ p 2 , ⋯   , a n \underset{\uparrow_{p_1}}{a_1},\underset{\uparrow_{p_2}}{a_2},\cdots,a_n p1a1,p2a2,,an
    • 从上面的关系式可以看出, 指针从 a i 移动到 a j 需要执行 Δ = j − i 单步移动操作 ★ 指针从a_i移动到a_j需要执行\Delta=j-i单步移动操作\bigstar 指针从ai移动到aj需要执行Δ=ji单步移动操作

内存中的数组而言
  • 设一个数组元素占用L=3个存储单元
    • a 1 , a 2 , a 3 ; a 4 , a 5 , a 6 a_1,a_2,a_3;a_4,a_5,a_6 a1,a2,a3;a4,a5,a6
    • 其中 a i 表示第 i 个存储单元 其中a_i表示第i个存储单元 其中ai表示第i个存储单元
  • 那么元素 e 0 占用 a 1 , a 2 , a 3 ; 元素 e 1 占用 a 4 , a 5 , a 6 那么元素e_0占用a_1,a_2,a_3;元素e_1占用a_4,a_5,a_6 那么元素e0占用a1,a2,a3;元素e1占用a4,a5,a6
    • L o c ( e 0 ) = a 1 , e 0 的起始地址就是 a 1 的地址 Loc(e_0)=a_1,e_0的起始地址就是a_1的地址 Loc(e0)=a1,e0的起始地址就是a1的地址
    • L o c ( e 1 ) = a 1 + 1 × L = a 1 + 1 × 3 = a 4 Loc(e_1)=a_1+1\times L=a_1+1\times3=a_4 Loc(e1)=a1+1×L=a1+1×3=a4
    • L o c ( e i ) = L o c ( e 0 ) + i × L = a 1 + i L = a 1 + i L Loc(e_i)=Loc(e_0)+i\times L=a_1+iL=a_{1+iL} Loc(ei)=Loc(e0)+i×L=a1+iL=a1+iL
    • L o c ( e j ) = L o c ( e i ) + ( j − i ) L Loc(e_j)=Loc(e_i)+(j-i)L Loc(ej)=Loc(ei)+(ji)L

B闭区间内的元素数量MatchedSize

  • M a t c h e d S i z e ( i n d e x i , i n d e x j ) 表示 , 序列 { a n } 的元素 a i 到元素 a j 之间连同两端包含了多少个元素 MatchedSize(index_i,index_j)表示,序列\{a_n\}的元素a_i到元素a_j之间连同两端包含了多少个元素 MatchedSize(indexi,indexj)表示,序列{an}的元素ai到元素aj之间连同两端包含了多少个元素

  • ∣ Δ ∣ = i n c r e m e n t ( i n d e x 1 , i n d e x 2 ) = ∣ i n d e x 2 − i n d e x 1 ∣ m ( s t a r t , e n d ) = M a t c h e d S i z e ( i n d e x 1 , i n d e x 2 ) = ∣ Δ ∣ + 1 = ∣ i n d e x 2 − i n d e x 1 ∣ + 1 |\Delta|=increment(index1,index2)=|index2-index1| \\ m(start,end)=MatchedSize(index1,index2)=|\Delta|+1=|index2-index1|+1 ∣Δ∣=increment(index1,index2)=index2index1∣m(start,end)=MatchedSize(index1,index2)=∣Δ∣+1=index2index1∣+1

  • offset&MatchedSize公式都是十分基础但是用途十分广泛的计数公式,比如

    • 活动日期的计算: 11 ∼ 29 号共有几天 ? d a y s = m ( 11 , 29 ) = 29 − 11 + 1 = 19 11\sim29号共有几天?days=m(11,29)=29-11+1=19 1129号共有几天?days=m(11,29)=2911+1=19

    • 排列数公式 ( n m ) = n ( n − 1 ) ( n − 2 ) ⋯ ( n − m + 1 ) 排列数公式\binom{n}{m}=n(n-1)(n-2)\cdots(n-m+1) 排列数公式(mn)=n(n1)(n2)(nm+1)

      • 则我们有 p − 1 = n − m ( 或者说 ( p − 1 ) + m = n ) ; 这样 , ( p − 1 ) ! = ( n − m ) ! ; ∏ k = 0 m − 1 ( n − k ) = n ! ( n − m ) ! 则我们有p-1=n-m(或者说(p-1)+m=n); \\这样,(p-1)!=(n-m)!; \\ \prod_{k=0}^{m-1}(n-k)=\frac{n!}{(n-m)!} 则我们有p1=nm(或者说(p1)+m=n);这样,(p1)!=(nm)!;k=0m1(nk)=(nm)!n!
    • 模式串匹配算法(朴素匹配/kmp)

    • 特殊矩阵压缩/解压公式

      • k对角矩阵,其第i行形如:

        • 0 ⋯ 0 , a i , j 1 , ⋯   , a i , j k , 0 ⋯ 0 0\cdots0,a_{i,j_1},\cdots,a_{i,j_k},0\cdots 0 00,ai,j1,,ai,jk,00
      • 问, a i , j k 前面的非零元素有几个 a_{i,j_k}前面的非零元素有几个 ai,jk前面的非零元素有几个;

        • 上面的问题看似不是MatchedSize的应用场合,但其实,稍微想一下,也可以转化为MatchedSize

        • 0 ⋯ 0 , a i , j 1 , ⋯   , a i , j k − 1 ⏟ 几个元素 ? , a i , j k , 0 ⋯ 0 0\cdots0,\underbrace{a_{i,j_1},\cdots,a_{i,j_{k-1}}}_{几个元素?},a_{i,j_k},0\cdots 0 00,几个元素? ai,j1,,ai,jk1,ai,jk,00

        • m ( 1 , k − 1 ) = j k − 1 − j 1 + 1 m_{(1,k-1)}=j_{k-1}-j_1+1 m(1,k1)=jk1j1+1

        • 特别的 , 三对角矩阵 ( k = 3 ) 中 , 第 i 行元素 a i , j 前面的非零元素有几个 ? 特别的,三对角矩阵(k=3)中,第i行元素a_{i,j}前面的非零元素有几个? 特别的,三对角矩阵(k=3),i行元素ai,j前面的非零元素有几个?

          • j 1 = i − 1 , j k − 1 = j − 1 j_1=i-1,j_{k-1}=j-1 j1=i1,jk1=j1
          • e l e m s = m ( i − 1 , j − 1 ) = ( j − 1 ) − ( i − 1 ) + 1 = j − i + 1 elems=m(i-1,j-1)=(j-1)-(i-1)+1=j-i+1 elems=m(i1,j1)=(j1)(i1)+1=ji+1
      • 问: a i ⋯ a j − 1 ⏟ 子串长度为 L a j \underbrace{a_i\cdots a_{j-1}}_{子串长度为L}a_{j} 子串长度为L aiaj1aj

        • 其中 a j 的序号为 y 其中a_j的序号为y 其中aj的序号为y
        • 那么 a i 的序号 x 为多少 ? 那么a_i的序号x为多少? 那么ai的序号x为多少?
          • 坐标差 Δ = j − i = L 坐标差\Delta=j-i=L 坐标差Δ=ji=L
          • a i a i + 1 ⋯ a j − 1 a j ⏟ 子串长度为 L + 1 \underbrace{a_ia_{i+1}\cdots a_{j-1}a_{j}}_{子串长度为L+1} 子串长度为L+1 aiai+1aj1aj
            • L + 1 = y − x + 1 即 : x = y − L L+1=y-x+1即: x=y-L L+1=yx+1:x=yL
          • a i a i + 1 ⋯ a j − 1 a j ⏟ 子串长度为 L a_i\underbrace{a_{i+1}\cdots a_{j-1}a_{j}}_{子串长度为L} ai子串长度为L ai+1aj1aj
            • x = y − L x=y-L x=yL

😎小结

  • 从一维序列的计数公式&坐标公式的各种形式上看

  • 关系式 ∣ j − i ∣ = ∣ Δ ( L ) ∣ 足以解决所有相关问题 ( 以坐标差 Δ 为核心 ) 关系式|j-i|=|\Delta(L)|足以解决所有相关问题(以坐标差\Delta为核心) 关系式ji=∣Δ(L)足以解决所有相关问题(以坐标差Δ为核心)

    • 坐标差 = 增量长度 j − i = Δ = L [ a i , a j − 1 ] = L [ a j , a i + 1 ] ⩾ 0 ( i − j = − Δ ) (core) \\坐标差=增量长度 \\ j-i=\Delta=L_{[a_{i},a_{j-1}]}=L_{[a_{j},a_{i+1}]}\tag{core}\geqslant 0 \\ (i-j=-\Delta) 坐标差=增量长度ji=Δ=L[ai,aj1]=L[aj,ai+1]0(ij=Δ)(core)

      L [ a i , a j ] = ∣ Δ ∣ + 1 = ∣ j − i ∣ + 1 L_{[a_{i},a_{j}]}=|\Delta|+1=|j-i|+1 L[ai,aj]=∣Δ∣+1=ji+1

    • 将坐标差 Δ 用闭区间距离 L 或 ( L ± 1 ) 表示出来 将坐标差\Delta用闭区间距离L或(L\pm 1)表示出来 将坐标差Δ用闭区间距离L(L±1)表示出来

    • L 通常是 a i ∼ a j 闭区间内的元素数量 , 这时候 Δ ( L ) = L − 1 L通常是a_i\sim a_j闭区间内的元素数量,这时候\Delta(L)=L-1 L通常是aiaj闭区间内的元素数量,这时候Δ(L)=L1

利用上面的关系式列等式, 所有关于 i , j , L 的值都可以一步计算的时间内得出 所有关于i,j,L的值都可以一步计算的时间内得出 所有关于i,j,L的值都可以一步计算的时间内得出

公式中都具有坐标差(假设i<j)

  • 闭区间元素数量 L = Δ + 1 = j − i + 1 闭区间元素数量L=\Delta+1=j-i+1 闭区间元素数量L=Δ+1=ji+1
  • 闭区间左端点坐标 i 可以由 : i = j − Δ = j − L + 1 ; 闭区间左端点坐标i可以由:i=j-\Delta=j-L+1; 闭区间左端点坐标i可以由:i=jΔ=jL+1;
  • 右端点坐标 j = i + Δ = i + L − 1 右端点坐标j=i+\Delta=i+L-1 右端点坐标j=i+Δ=i+L1

数组元素位置&起始地址

二维数组(矩阵)

  • 按行优先排列
  • m , n 分别表示矩阵的行数和列数 m,n分别表示矩阵的行数和列数 m,n分别表示矩阵的行数和列数
    • i ∈ [ 0 , m − 1 ] 是行下标的维界 i\in[0,m-1]是行下标的维界 i[0,m1]是行下标的维界
    • j ∈ [ 0 , n − 1 ] 是列下标的维界 j\in[0,n-1]是列下标的维界 j[0,n1]是列下标的维界
  • a i , j 表示矩阵中的第 i 行第 j 列元素 a_{i,j}表示矩阵中的第i行第j列元素 ai,j表示矩阵中的第i行第j列元素
    • 例如, 第一个元素坐标为 a 00 第一个元素坐标为a_{00} 第一个元素坐标为a00
  • L 表示数组中的元素占的存储单元数 , 比如字节数 L表示数组中的元素占的存储单元数,比如字节数 L表示数组中的元素占的存储单元数,比如字节数
  • L o c ( a i , j ) 表示元素 a i , j 在内存中的起始地址 Loc(a_{i,j})表示元素a_{i,j}在内存中的起始地址 Loc(ai,j)表示元素ai,j在内存中的起始地址

一维数组

  • 按行优先排列

  • m 分别表示一维数组的维数 m分别表示一维数组的维数 m分别表示一维数组的维数

    • i ∈ [ 0 , m − 1 ] 是行下标的维界 i\in[0,m-1]是行下标的维界 i[0,m1]是行下标的维界
  • a i 表示数组中下标为 i 的元素 a_{i}表示数组中下标为i的元素 ai表示数组中下标为i的元素

    • 例如, 第一个元素坐标为 a 0 第一个元素坐标为a_{0} 第一个元素坐标为a0
  • L 表示数组中的元素占的存储单元数 , 比如字节数 L表示数组中的元素占的存储单元数,比如字节数 L表示数组中的元素占的存储单元数,比如字节数

  • L o c ( a i ) 表示元素 a i 在内存中的起始地址 Loc(a_{i})表示元素a_{i}在内存中的起始地址 Loc(ai)表示元素ai在内存中的起始地址

    • a[0]a[1]a[2]a[i]
    • L o c ( a 1 ) = L o c ( a 0 ) + 1 × L 一种不太准确的 L o c ( a i ) 的理解 : ↿ L a [ 0 ] , a [ 1 ] , ⋯   , a [ i − 1 ] ⏟ i − 1 ⏞ i 个元素 , ↿ a [ i ] , ⋯ 比较合适的理解 L o c ( a i ) : a [ 0 ] ↿ L o c , a [ 1 ] , ⋯   , a [ i − 1 ] ⏟ i − 1 ⏞ i 个元素 , a [ i ] , ⋯ 所以 : L o c ( a i ) = L o c ( a 0 ) + i × L Loc(a_1)=Loc(a_0)+1\times L \\一种不太准确的Loc(a_i)的理解: \\\underset{\underset{L}{\upharpoonleft}}{} \overbrace{a[0],\underbrace{a[1],\cdots,a[i-1]}_{i-1}}^{i个元素},\underset{\upharpoonleft}{}a[i],\cdots \\比较合适的理解Loc(a_i): \\\overbrace{{\underset{\upharpoonleft_{Loc}}{a[0]}},\underbrace{a[1],\cdots,a[i-1]}_{i-1}}^{i个元素},a[i],\cdots \\所以: Loc(a_i)=Loc(a_0)+i\times L Loc(a1)=Loc(a0)+1×L一种不太准确的Loc(ai)的理解:La[0],i1 a[1],,a[i1] i个元素,a[i],比较合适的理解Loc(ai):Loca[0],i1 a[1],,a[i1] i个元素,a[i],所以:Loc(ai)=Loc(a0)+i×L

  • L o c ( a i ) = L o c ( a 0 ) + i × L Loc(a_i)=Loc(a_0)+i\times L Loc(ai)=Loc(a0)+i×L

  • L o c ( a i , j ) = L o c ( a 0 , 0 ) + i × s i z e o f ( r o w ) + j × L s i z e o f ( r a w ) = m × L L o c ( a i , j ) = L o c ( a 0 , 0 ) + ( i × m + j ) × L Loc(a_{i,j})=Loc(a_{0,0})+i\times sizeof(row)+j\times L \\sizeof(raw)=m\times L \\Loc(a_{i,j})=Loc(a_{0,0})+ (i\times m+j)\times L Loc(ai,j)=Loc(a0,0)+i×sizeof(row)+j×Lsizeof(raw)=m×LLoc(ai,j)=Loc(a0,0)+(i×m+j)×L

三角矩阵的压缩

  • 三角矩阵(方阵) A [ 1... n ] [ 1... n ] A[1...n][1...n] A[1...n][1...n],包括
    • 上三角矩阵(下三角所有元为同一个常量) j ⩽ i j\leqslant i ji
    • 下三角矩阵(上三角所有元素为同一个常量) i ⩽ j i\leqslant j ij
  • 上下三角包含 n ( n + 1 ) 2 个元素 ; 在加上 ( 占据矩阵其余位置的 ) 一个常量 c 上下三角包含\frac{n(n+1)}{2}个元素;在加上(占据矩阵其余位置的)一个常量c 上下三角包含2n(n+1)个元素;在加上(占据矩阵其余位置的)一个常量c
  • 所以需要一个大小 至少 ‾ 为 n ( n + 1 ) 2 + 1 维的数组来保存必要元素 所以需要一个大小\underline{至少}为\frac{n(n+1)}{2}+1维的数组来保存必要元素 所以需要一个大小至少2n(n+1)+1维的数组来保存必要元素
    • A 三角 [ 1 , . . . , n ] [ 1 , . . . , n ] ; B [ 1... 1 2 n ( n + 1 ) + 1 ] A_{三角}[1,...,n][1,...,n];B[1...\frac{1}{2}{n(n+1)}+1] A三角[1,...,n][1,...,n];B[1...21n(n+1)+1]

上三角

按行优先
  • 从矩阵的第一个元素 a 0 , 0 开始 , 按行扫描 , 一直到 a i , j , 期间遇到的属于上三角 ( a i , j ; i ⩽ j ) 的元素的个数 : 从矩阵的第一个元素a_{0,0}开始,按行扫描,一直到a_{i,j}, \\期间遇到的属于上三角(a_{i,j};i\leqslant j)的元素的个数: \\ 从矩阵的第一个元素a0,0开始,按行扫描,一直到ai,j,期间遇到的属于上三角(ai,j;ij)的元素的个数:

    第x行行x上属于上三角的元素的个数
    1 n n n
    2n-1
    3 n − 2 n-2 n2
    x x x n − ( x − 1 ) n-(x-1) n(x1)
    i − 1 ( x = i − 1 时 ) i-1(x=i-1时) i1(x=i1) n − ( i − 1 − 1 ) = n − i + 2 n-(i-1-1)=n-i+2 n(i11)=ni+2
    i(特别的) j − i + 1 j-i+1 ji+1
    • 如果 B [ 0... ] , 那么 k 0 = S i − 1 + s i − 1 ; S i − 1 = ( i − 1 ) ( 2 n − i + 2 ) 2 是前 i − 1 行的元素总数量 , s i = j − i + 1 是第 i 行的 a i , i 到 a i , j 的元素数量 k 0 = ( i − 1 ) ( 2 n − i + 2 ) 2 + ( j − i + 1 ) − 1 = ( i − 1 ) ( 2 n − i + 2 ) 2 + j − i 如果B[0...],那么k_0=S_{i-1}+s_i-1; \\S_{i-1}=\frac{(i-1)(2n-i+2)}{2}是前i-1行的元素总数量, \\s_i=j-i+1是第i行的a_{i,i}到a_{i,j}的元素数量 \\k_0=\frac{(i-1)(2n-i+2)}{2}+(j-i+1)-1=\frac{(i-1)(2n-i+2)}{2}+j-i 如果B[0...],那么k0=Si1+si1;Si1=2(i1)(2ni+2)是前i1行的元素总数量,si=ji+1是第i行的ai,iai,j的元素数量k0=2(i1)(2ni+2)+(ji+1)1=2(i1)(2ni+2)+ji

    • 如果 B [ 1... ] , 那么 k 1 = S i − 1 + s i ; k 1 = ( i − 1 ) ( 2 n − i + 2 ) 2 + j − i + 1 如果B[1...],那么k_1=S_{i-1}+s_i; \\k_1=\frac{(i-1)(2n-i+2)}{2}+j-i+1 如果B[1...],那么k1=Si1+si;k1=2(i1)(2ni+2)+ji+1

映射公式用法

k 0 ( i , j ) = { ( i − 1 ) ( 2 n − i + 2 ) 2 + j − i ; ( i ⩽ j ) n ( n + 1 ) 2 ; ( j < i ) 即 A [ i ] [ j ] = B [ k ( i , j ) ] k 根据 B 数组的要求而决定选用 k 0 还是 k 1 ; 实际上更多的用的前者 k_0(i,j)=\begin{cases} \frac{(i-1)(2n-i+2)}{2}+j-i ;(i\leqslant j) \\\frac{n(n+1)}{2};(j<i) \end{cases} \\ 即A[i][j]=B[k(i,j)] \\k根据B数组的要求而决定选用k_0还是k_1;实际上更多的用的前者 k0(i,j)={2(i1)(2ni+2)+ji;(ij)2n(n+1);(j<i)A[i][j]=B[k(i,j)]k根据B数组的要求而决定选用k0还是k1;实际上更多的用的前者

按列优先
  • k 1 ( i , j ) = 1 2 j ( j − 1 ) + i k_1(i,j)=\frac{1}{2}{j(j-1)}+i k1(i,j)=21j(j1)+i

下三角矩阵

  • 和上三角十分相似的讨论过程
  • 压缩过程行列情况对调(按行优先/按列优先)
  • 本质上是等差数列求和公式的应用

😀公式使用条件

k 0 & k 1 的关系 k_0\&k_1的关系 k0&k1的关系
  • 经过前面的讨论, 可以知道 k 0 = k 1 − 1 ; 或者 k 1 = k 0 + 1 可以知道k_0=k_1-1;或者k_1=k_0+1 可以知道k0=k11;或者k1=k0+1
  • 之后我们仅讨论 k 0 或者 k 1 之后我们仅讨论k_0或者k_1 之后我们仅讨论k0或者k1
A [ 0... ] v s A [ 1... ] A[0...] vs A[1...] A[0...]vsA[1...]
  • 有时, 矩阵的坐标是从 0 开始的 : i ∈ [ 0 , n ] , j ∈ [ 0 , n ] 矩阵的坐标是从0开始的:i\in[0,n],j\in[0,n] 矩阵的坐标是从0开始的:i[0,n],j[0,n]
  • 前的公式都是在 i ∈ [ 1 , n ] , j ∈ [ 1 , n ] 情况下推导的 前的公式都是在i\in[1,n],j\in[1,n]情况下推导的 前的公式都是在i[1,n],j[1,n]情况下推导的
  • 如果要求用 a i , j ; i ∈ [ 0 , n ] , j ∈ [ 0 , n ] 来计算 k , 那么必须要一定的调整 如果要求用a_{i,j};i\in[0,n],j\in[0,n]来计算k,那么必须要一定的调整 如果要求用ai,j;i[0,n],j[0,n]来计算k,那么必须要一定的调整
  • 幸运的是,这个调整比较简单, 只需要将 a i , j 直接映射 a i + 1 , j + 1 就可以了 只需要将a_{i,j}直接映射a_{i+1,j+1}就可以了 只需要将ai,j直接映射ai+1,j+1就可以了

对称矩阵

  • 对称矩阵和三角矩阵十分相近

  • 不同的是对称矩阵的特点: a i , j = a j , i a_{i,j}=a_{j,i} ai,j=aj,i

  • 这意味着 , 如果对称矩阵将上三角 ( i ⩽ j ) 压缩到数组 B 中 , 并且要求的是 a p , q ( p ⩾ q ) 的压缩位置 , 那么可以利用公式 a q , p = a p , q 来解压 这意味着,如果对称矩阵将上三角(i\leqslant j)压缩到数组B中, \\并且要求的是a_{p,q}(p\geqslant q)的压缩位置,那么可以利用公式a_{q,p}=a_{p,q}来解压 这意味着,如果对称矩阵将上三角(ij)压缩到数组B,并且要求的是ap,q(pq)的压缩位置,那么可以利用公式aq,p=ap,q来解压

    k 0 ( i , j ) = { i ( i − 1 ) 2 + j − 1 ; i ⩾ j j ( j − 1 ) 2 + i − 1 ; i ⩽ j k_0(i,j)=\begin{cases} \frac{i(i-1)}{2}+j-1;i\geqslant j \\ \frac{j(j-1)}{2}+i-1;i\leqslant j \end{cases} k0(i,j)={2i(i1)+j1;ij2j(j1)+i1;ij

三对角矩阵

  • 对角阵/三对角矩阵均为方阵
    • 记为 A n × n 记为A_{n\times n} 记为An×n
    • 二维数组形式 A [ 1 , . . . , n ] [ 1 , . . . , n ] 二维数组形式A[1,...,n][1,...,n] 二维数组形式A[1,...,n][1,...,n]
i=1( Q − 1 Q_{-1} Q1)(虚拟) Q 0 Q_0 Q0 Q 1 Q_1 Q1
2 Q 2 Q_2 Q2Q Q 4 Q_4 Q4
3 Q 5 Q_5 Q5Q Q 7 Q_7 Q7
4 ⋮ \vdots ⋮ \vdots
QQQ
QQ
  • 第 1 行到 i − 1 行每行多有三个元素 ( 补上的虚拟元素 Q − 1 后面再 − 1 , 则 s i − 1 = 3 ( i − 1 ) − 1 ) 第1行到i-1行每行多有三个元素(补上的虚拟元素Q_{-1}后面再-1,则s_{i-1}=3(i-1)-1) 1行到i1行每行多有三个元素(补上的虚拟元素Q1后面再1,si1=3(i1)1)

  • 第 i 行有 b i = j − ( i − 1 ) 个元素 第i行有b_i=j-(i-1)个元素 i行有bi=j(i1)个元素

    • 因为,三对角矩阵的斜对角区域的每一行的三个元素可以表示为: a i , i − 1 , a i , i , a i , i + 1 a_{i,i-1},a_{i,i},a_{i,i+1} ai,i1,ai,i,ai,i+1

    • 这时
      j = { i − 1 i i + 1 j=\begin{cases} i-1 \\i \\i+1 \end{cases} j= i1ii+1

压缩公式

  • 将矩阵 A [ 1 , . . . , n ] [ 1 , . . . , n ] 中的元素 a i , j 压缩到 B 数组中的下标为 k = k ( i , j ) 的位置 将矩阵A[1,...,n][1,...,n]中的元素a_{i,j}压缩到B数组中的下标为k=k(i,j)的位置 将矩阵A[1,...,n][1,...,n]中的元素ai,j压缩到B数组中的下标为k=k(i,j)的位置

    • 计算 k 的原理是 , 计算 a i , j 前面的元素个数 : k b e f o r e ( i , j ) = 3 ( i − 1 ) − 1 + j − ( i − 1 ) = 2 i + j − 3 计算k的原理是,计算a_{i,j}前面的元素个数:k_{before}(i,j)=3(i-1)-1+j-(i-1)=2i+j-3 计算k的原理是,计算ai,j前面的元素个数:kbefore(i,j)=3(i1)1+j(i1)=2i+j3

    • B [ 0 , . . . , n − 1 ] , 从 B [ 0 ] 开始存放元素 a 0 , 0 , . . B[0,...,n-1],从B[0]开始存放元素a_{0,0},.. B[0,...,n1],B[0]开始存放元素a0,0,..
      k 0 ( i , j ) = 3 ( i − 1 ) − 1 + j − ( i − 1 ) = 2 i + j − 3 k_0(i,j)=3(i-1)-1+j-(i-1)=2i+j-3 k0(i,j)=3(i1)1+j(i1)=2i+j3

  • B [ 1 , . . . , n ] , 从 B [ 1 ] 开始存放元素 a 0 , 0 , . . . B[1,...,n],从B[1]开始存放元素a_{0,0},... B[1,...,n],B[1]开始存放元素a0,0,...

    这种情况也是有的(比如,我们用B[0]保存其他元信息,比如长度)
    k 1 ( i , j ) = k 0 ( i , j ) + 1 = 2 i + j − 2 k_{1}(i,j)=k_{0}(i,j)+1=2i+j-2 k1(i,j)=k0(i,j)+1=2i+j2

确定数组中的元素解压后的行/列公式

  • 按行优先
确定行

i ( k ) = ⌊ k + 1 3 + 1 ⌋ = ⌊ k + 1 3 ⌋ + 1 = ⌊ k + 4 3 ⌋ i(k)=\lfloor{\frac{k+1}{3}+1}\rfloor=\lfloor{\frac{k+1}{3}}\rfloor+1 \\=\left\lfloor\frac{k+4}{3}\right\rfloor i(k)=3k+1+1=3k+1+1=3k+4

  • 例如

    • i ( 0 ) = 1 i ( 1 ) = 1 i ( 2 ) = 2 ⋮ i(0)=1 \\i(1)=1 \\i(2)=2 \\ \vdots i(0)=1i(1)=1i(2)=2
我们来推导一下

i = 1 ; k = { ( − 1 ) ( 虚拟 ) 0 1 i = 2 ; k = { 2 3 4 i = 3 ; k = { 5 6 7 ⋮ i = i ; k = { 3 ( i − 1 ) − 1 3 ( i − 1 ) 3 ( i − 1 ) + 1 k + 1 = { 3 ( i − 1 ) 3 ( i − 1 ) + 1 3 ( i − 1 ) + 2 k + 1 3 = { ( i − 1 ) ( i − 1 ) + 1 3 ( i − 1 ) + 2 3 k + 1 3 + 1 = { i i + 1 3 i + 2 3 可见 : 上式子两边同时向下取整 , 就得到 k 映射到 i 的函数 ⌊ k + 1 3 + 1 ⌋ = ⌊ k + 1 3 ⌋ + 1 = i i ( k ) = ⌊ k + 1 3 + 1 ⌋ = ⌊ k + 1 3 ⌋ + 1 i=1;k=\begin{cases} (-1)(虚拟) \\0 \\1 \end{cases}\\ i=2;k=\begin{cases} 2 \\3 \\4 \end{cases}\\ i=3;k=\begin{cases} 5 \\6 \\7 \end{cases}\\ \vdots\\ i=i;k=\begin{cases} 3(i-1)-1 \\3(i-1) \\3(i-1)+1 \end{cases}\\ {k+1}=\begin{cases} 3(i-1) \\3(i-1)+1 \\3(i-1)+2 \end{cases}\\ \frac{k+1}{3}=\begin{cases} (i-1) \\(i-1)+\frac{1}{3} \\(i-1)+\frac{2}{3} \end{cases}\\ \frac{k+1}{3}+1=\begin{cases} i \\i+\frac{1}{3} \\i+\frac{2}{3} \end{cases}\\ 可见:上式子两边同时向下取整,就得到k映射到i的函数 \\ \lfloor{\frac{k+1}{3}+1}\rfloor=\lfloor{\frac{k+1}{3}}\rfloor+1 =i \\ i(k)=\lfloor{\frac{k+1}{3}+1}\rfloor=\lfloor{\frac{k+1}{3}}\rfloor+1 i=1;k= (1)(虚拟)01i=2;k= 234i=3;k= 567i=i;k= 3(i1)13(i1)3(i1)+1k+1= 3(i1)3(i1)+13(i1)+23k+1= (i1)(i1)+31(i1)+323k+1+1= ii+31i+32可见:上式子两边同时向下取整,就得到k映射到i的函数3k+1+1=3k+1+1=ii(k)=3k+1+1=3k+1+1

确定列
  • j ( k , i ) = k − 2 i + 3 ; 又因为 i = i ( k ) = ⌊ k + 1 3 + 1 ⌋ 或者 j ( k ) = j ( k , i ( k ) ) = k − 2 ( ⌊ k + 1 3 + 1 ⌋ ) + 3 j(k,i)=k-2i+3;又因为i=i(k)=\lfloor{\frac{k+1}{3}+1}\rfloor \\或者 \\j(k)=j(k,i(k))=k-2(\lfloor{\frac{k+1}{3}+1}\rfloor)+3 j(k,i)=k2i+3;又因为i=i(k)=3k+1+1或者j(k)=j(k,i(k))=k2(⌊3k+1+1⌋)+3
posted @   xuchaoxin1375  阅读(18)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示