根据递推公式构造系数矩阵用于快速幂

简单的例子

Fibonacci数列

考虑 Fibonacci 数列,

F(n)=F(n1)+F(n2)

将右边两项看做是一个列向量的形式,令
Xn1={Fn1Fn2}

很容易得到 Xn 的形式,即
Xn={FnFn1}

现在的任务就是找到一个系数矩阵 A ,使得AXn1=Xn,且 A 需与n无关。
如果能够找到这个 A ,则易知An1X1=Xn,于是可以利用矩阵快速幂计算出 Xn 。这样就可以在 O(logn) 的时间内计算出指定的 Fibonacci 数。
这个矩阵很容易找,观察易得
A={1110}(1)

Fibonacci数列变种

推广一下,如果令 Fn=aFn1+bFn2 ,则系数矩阵为

A={a1b0}(2)

利用二项式展开构造矩阵

计算k次方和

Fibonacci 数列只是最简单的例子,对于稍微复杂一点的例子,二项式展开是常用的一项技术。
考虑计算:

Sn=i=1nik

易得
Sn=nk+Sn1

如果仿照 Fibonacci 数列,令
Xn1={nkSn1}


Xn={(n+1)kSn}

此时,可求出
A=(n+1n)k101

这个系数矩阵很明显是不能用的,因为它与 n 有关,无法将递推公式转化为矩阵的幂运算。
这里需要使用二项式展开。
Sn=(n1+1)k+Sn1=C0k(n1)k+C1k(n1)k1++Ckk+Sn1

此时,如果令
Xn1=(n1)k(n1)k1(n1)0Sn1

则有
Xn=nknk1n0Sn

现在的任务与刚才一样,找到一个系数矩阵 A ,使得AXn1=Xn,且 A 需与n无关。
有关 Sn 的递推公式实际上就指明了 A 的最后一行。而利用二项式展开很容易得到其他行。

A=C0k00C0kC1kC0k1C1kCkkCk1k1C00Ckk0001(3)

最后有
An1X1=Xn


X1={1 1  1}T

利用该系数矩阵可以在 O(k3logn) 时间内计算出 k 次方的和。

更一般的例子

再考虑一个一般情况:

Sn=i=1n(ai+b)k

与刚才几乎一模一样,有
Sn=[a(n1)+(a+b)]k+Sn1=C0kak(n1)k+C1kak1(a+b)(n1)k1++Ckk(a+b)k+Sn1

剩下的步骤,也几乎完全与之前的一样,令
Xn1=(n1)k(n1)k1(n1)0Sn1


Xn=nknk1n0Sn

同样,有关 Sn 的递推公式实际上就指明了 A 的最后一行,其他行则利用二项式展开得到。

A=C0k00C0kakC1kC0k1C1kak1(a+b)CkkCk1k1C00Ckk(a+b)k0001(4)

更复杂的例子

假设要计算如下和式:

Sn=i=1nikki

同样,将其写成递推公式,有
Sn=nkkn+Sn1=(n1+1)kk(n1)+1+Sn1=C0k(n1)kk(n1)+1+C1k(n1)k1k(n1)+1++Ckkk(n1)+1+Sn1

将与 n 有关的项抽出来作为列向量,令
Xn1=(n1)kk(n1)+1(n1)k1k(n1)+1(n1)0k(n1)+1Sn1


Xn=nkkn+1nk1kn+1n0kn+1Sn

同样,有关 Sn 的递推公式说明了系数矩阵 A 的最后一行。而其他行仍然可以由二项式展开得到,只是相差了一个系数k而已,这很容易解决。
最后,有

A=kC0k00C0kkC1kkC0k1C1kkCkkkCk1k1kC00Ckk0001(5)

部分题目

POJ3070利用了矩阵1,hdu3369利用了矩阵3和4,hdu3483利用了矩阵5。

  • 32
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值