矩阵乘法小结

来源:互联网 发布:网络打字员工作 编辑:程序博客网 时间:2024/06/05 16:13
矩阵乘法小结
     由于最近连续做了两道矩阵乘法的题目,所以我决定做个小结。那就先让我们看一看这两题
第一题:数格子
题意:一共有多少种办法用2*1的多米诺骨牌填满4*N的矩阵。答案需mod m。
数据范围:30%数据:n<=8    60%:n<=10^5    100%:n<=10^9 m<=10^5
题解:30%想怎么暴力就怎么暴力,我就不讲了。
         60%的话很容易想到状压dp,设状态f[i,j]表示答案,i表示dp到第i行,j是一个二进制状态,第 k位为1表示本行第k列放置了一个纵向的多米诺骨牌,另一端在(i+1,k),0表示此位置要么和同行相邻的位置放了一个横向的多米诺骨牌,要么和(i-1,k)一起放了一个纵向的多米诺骨牌。转移就是 f[i,j]=∑f[i-1,k],并满足k状态可以转移到j,因为不管在哪一行两个状态是否能从一个状态转移到另一个是确定的,所以可以预处理标记数组bz[j,k]=1表示j可转移到k,=0则表示不能。这样只有bz[k,j]=1我们才转移,时间复杂度为O(n*2^8),只能过60分。
        100%就需要用到高级算法——矩阵乘法了。因为上面也说了,不管在哪一行两个状态是否从一个状态转移到另一个能是确定的,也就是每个状态能由哪些状态转移到它是确定的,这符合矩阵乘法的性质,可以把bz数组当做一个矩阵,然后设一个状态序列a[j],j表示dp中的二进制状态,初始情况若j状态在i=1时合法则a[j]=1,否则=0。每行的转移等同于让a乘一次bz,要转移n-1次,就乘n-1次bz,然后用快速幂就能解决了。O(log2n*2^12)
第二题:天使的分裂
题意:有一个数列f是一个斐波拉契数列,f[0]=1 f[1]=1 f[i]=f[i-1]+f[i-2] 另有一个数列F[n]=∑f[i]f[n-i](i=0~n) 问ans=∑F[i](i=0~n) mod 998244353有多大
        40%:n<=2*10^3 70%:n<=10^7 100%:n<=10^18
题解:40%:强行模拟,不讲
           70%:想到f是斐波拉契数列,f[i]=f[i-1]+f[i-2],所以有了一种特殊的技巧将F数组强行转成递推形式。F[n]=∑f[i]*f[n-i](i=0~n)=∑(f[i-1]+[i-2])*f[n-i](i=2~n)+f[0]*f[n]+f[1]*f[n-1]=∑f[i]*f[n-i-1](i=0~n-1)-f[0]*f[n-1]+∑f[i]*f[n-i-2](i=0~n-2)+f[0]*f[n]+f[1]*f[n-1]=F[n-1]+F[n-2]+f[0]*f[n]+f[1]*f[n-1]-f[0]*f[n-1]=F[n-1]+F[n-2]+f[n] 这样直接递推,时间复杂度O(n)
数据范围:100%:像这种递推式,一般都是矩阵乘法的模型,设一个状态序列a[1~5],a[1]=F[i] a[2]=F[i-1] a[3]=f[i+1
a[4]=f[i] a[5]=sum[i-1](sum[i]=∑F[j](j<=i))然后设转移数组b,b数组是怎样自己思考,然后a=a*b^n,最后输出a[5]就行了。
矩阵乘法小结:做了两题矩阵乘法,知道矩阵乘法有一个状态序列和转移矩阵,要用好它就得仔细思考这两个数组里应该填什么数的。然后发现矩阵乘法的用处首先是优化递推式,可以借助矩阵乘法的结合律利用快速幂实现递推式的快速转移。至于为什么矩阵乘法具有结合律,我也不知道。不过等我实力增强到一定程度,我或许都可以自己证明这个结论了。所以我现在就先留下这个悬念,等以后再解开它。其实我们学习也是这样,不要指望什么都能弄明白,有些东西等你长大了,经验多了,实力强了,你自然能弄明白了。我们要做的只有脚踏实地,把该弄明白的弄明白,该做好的做好就行了。其实刚才的这段哲学道理是我的化学老师说的,我的化学老师是个哲学家(怎么我好想在里面加点符号啊,易建联)。有点扯远了,回归正题,矩阵乘法第二个用处就是优化非max/min式,二进制状态的转移是确定的状压 dp,也是通过矩阵乘法结合律利用快速幂进行飞快的状态转移。
      矩阵乘法由于时间复杂度一般是O(log2n),所以对于n特别大,只要是n<=10^9或爆longint的数,都可以考虑矩阵乘法,看看能不能把问题转换成递推式,或者特殊的状压dp。
      好了,矩阵乘法的小结就到这里,要真正能灵活应用矩阵乘法还需要我们多加练习,加油!
1 0