zoukankan      html  css  js  c++  java
  • [矩阵加速]TR的数列

    题目描述

    TR非常喜欢数学,经常一个人拿出草稿纸研究奇奇怪怪的数学问题,最近,他突然对数列产生了兴趣,他找到一个数列,类似于斐波拉契,即:Tn=1*f1+2*f2+3*f3+……+n*fn    (fn为斐波拉契的第n项值)

    现在TR想请你帮忙求Tn%m的值

    输入

    两个用空格隔开的整数n和m

    1≤n,m≤2^31-1

    输出

    Tn mod m的值

    样例输入

    5 5
    

    样例输出

    1

    解题思路

    首先先明白什么是矩阵的乘法

    两个矩阵的乘法需满足一个条件就是矩阵A的列数要等于矩阵B的行数才能相乘。

    它们构造了一个C矩阵。

    如:A(n行,m列),B(m行,p列),则C(n行,p列).

    C(i,j) = A(i,1) * B(1,j) + A(i,2) * B(2,j) ...... +A(i,m) * B(m,j)

    于是就有矩阵乘法的模板。

    要做这道题是需要会做求斐波那契的第n项的矩阵加速

    我们定义A:[f1,f2].

    Begin{bmatrix} 0&1 \ 1&1 end{bmatrix}

    则 A * (B)^n-2即可得到fn。

    这里我们还要用矩阵快速幂。

    这就是矩阵加速的基本定义。

    然而这一道题显然是进阶的。

    在这里给出两种方法。

    1.

    T_{i} = T_{i-1} + i*f_{i}

    那么我们就需要将后面那一块用递推表示出来,我们姑且用P定义

    则很显然可以推出来这一个东西。

    P_{i - 1} + P_{i - 2} = (i - 2) * f_{i - 2} + f_{i - 1}

    P_{i} = P_{i - 1} + P_{i - 2} + f_{i - 2} + f_{n}

    既然都可这样进行递推了,那么我们将它放到矩阵当中就可以进行运算

    我们定义

    Aegin{bmatrix} T_i &P_{i} &P_{i+1} &f_{i} &f_{i+1} end{bmatrix}

    Begin{bmatrix} 1 & 0 & 0 & 0 &0 \ 0& 0 &1 &0 &0 \ 1 & 1 & 1 &0 &1 \ 0& 0 & 2 & 0 &1 \ 0 & 0 & 1 & 1 &1 end{bmatrix}

    那么仅仅需要A * B^(n - 1)即可

     scanf ("%d%d",&n,&mod);
        A.n = 1;
        A.m = 5;
        B.n = B.m = 5;
        A.c[1][1] = 1;
        A.c[1][2] = 1;
        A.c[1][3] = 2;
        A.c[1][4] = 1;
        A.c[1][5] = 1;
        B.c[1][1] = B.c[2][3] = B.c[3][1] = B.c[3][2] = B.c[3][3] = 1;
        B.c[4][5] = B.c[5][3] = B.c[5][4] = B.c[5][5] = 1;
        B.c[4][3] = 2;
        C = A * qkpow(B,n - 1);
        printf("%lld",C.c[1][1]);

    2.

    换一种构造方式

    我们如果用斐波那契前i项和来推的话其实也可推出来。

    至于怎么做,给一个基情链接,只不过有一个地方好像是错了。代码实现也跟我不怎么一样,希望了解思想而自己做出来结果,不然的话。真的会被弄晕的。

    不得不说矩阵乘法的代码都很奇葩。

    scanf ("%d%d",&n,&mod);
        A.n = 1;
        A.m = 4;
        B.n = B.m = 4;
        A.c[1][1] = 0;
        A.c[1][2] = 1;
        A.c[1][3] = 1;
        A.c[1][4] = 1;
        B.c[1][1] = B.c[2][1] = B.c[2][2] = B.c[3][4] = B.c[4][2] = B.c[4][3] = B.c[4][4] = 1;
        C = A * qkpow(B,n - 1);
        printf("%lld",(C.c[1][2] * n - C.c[1][1] + mod) % mod);

    有些东西我直接进行处理的,可能没这么好懂。

  • 相关阅读:
    上班不再能上msn了
    小龟不用冬眠了
    Sonne学摄影(3)上海汽车展汽车
    新年提醒银行卡的用户注意了
    转贴:49届世乒赛海外名将介绍究竟谁会对中国队构成威胁??
    用两个词形容现在的生活:忙碌,充实
    终于加入胖友一族
    上海人
    相互残杀
    王励勤,好样的!看49届世乒赛男单决赛
  • 原文地址:https://www.cnblogs.com/lover-fucker/p/13566684.html
Copyright © 2011-2022 走看看