题目描述
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列).
于是就有矩阵乘法的模板。
要做这道题是需要会做求斐波那契的第n项的矩阵加速
我们定义A:[f1,f2].
则 A * (B)^n-2即可得到fn。
这里我们还要用矩阵快速幂。
这就是矩阵加速的基本定义。
然而这一道题显然是进阶的。
在这里给出两种方法。
1.
那么我们就需要将后面那一块用递推表示出来,我们姑且用P定义
则很显然可以推出来这一个东西。
既然都可这样进行递推了,那么我们将它放到矩阵当中就可以进行运算
我们定义
那么仅仅需要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);
有些东西我直接进行处理的,可能没这么好懂。