目录
一.题目
题目描述
TR非常喜欢数学,经常一个人拿出草稿纸研究奇奇怪怪的数学问题,最近,他突然对数列产生了兴趣,他找到一个数列,类似于斐波拉契,即:Tn=1*f1+2*f2+3*f3+……+n*fn (fn为斐波拉契的第n项值)
现在TR想请你帮忙求Tn%m的值
输入
两个用空格隔开的整数n和m
输出
Tn mod m的值
样例输入
5 5
样例输出
1
提示
样例解释:
T5 = (1*1+2*1+3*2+4*3+5*5)%5 = 46%5 = 1
二.题解
这道题可以说不难也不简单,有很多种方法,我这里只讲一种,感兴趣的可以把你的方法发给我哟!
这道题要求的是=(1*f1+2*f2+3*f3+……+n*fn),于是我首先想到了构造一个4*4的矩阵,用去乘它。但是发现无论如何都构造不出来。但是我可以构造出=(n*f1+(n-1)*f2+(n-2)*f3+……+1*fn),也就是
* (写错了,[1,4]=1)
但是这不是我们想要的结果,于是我又想,我们可以这样得到(1*f1+2*f2+3*f3+……+n*fn):
对于n = 5时:
得到这个矩阵:的和
减去Tn即答案。
递推式:
就这样就完了。
三.代码
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define LL long long
LL n, m, ans;
struct node {
LL r, c, jz[10][10];
node operator * (const node& rhs) const{//矩阵乘法
node ans;
ans.r = r, ans.c = rhs.c;
for (register int i = 0; i <= 9; i ++)
for (register int j = 0; j <= 9; j ++)
ans.jz[i][j] = 0;
for (register int i = 1; i <= r; i ++)
for (register int j = 1; j <= rhs.c; j ++)
for (register int k = 1; k <= c; k ++)
ans.jz[i][j] = (ans.jz[i][j] + jz[i][k] * rhs.jz[k][j] % m) % m;
return ans;
}
}A, B, C;
inline void prepare (node &ans){
for (int i = 0; i <= 9; i ++)
for (int j = 0; j <= 9; j ++)
ans.jz[i][j] = 0;
}
inline node qkpow (node x, LL y){//矩阵快速幂
node ans;
prepare (ans);
ans.r = ans.c = 4;
for (int i = 1; i <= ans.r; i ++)
ans.jz[i][i] = 1;
while (y > 0){
if (y % 2 == 1)
ans = ans * x;
x = x * x;
y /= 2;
}
return ans;
}
int main (){
scanf ("%lld %lld", &n, &m);
B.r = 4, B.c = 4;
B.jz[1][1] = B.jz[2][1] = B.jz[3][1] = B.jz[3][2] = B.jz[2][3] = B.jz[3][3] = B.jz[1][4] = B.jz[2][4] = B.jz[3][4] = B.jz[4][4] = 1;//构造B矩阵
C.r = 1, C.c = 4;
C.jz[1][3] = C.jz[1][2] = 1, C.jz[1][1] = 2, C.jz[1][4] = 3;//构造C矩阵
C = C * qkpow (B, n - 2);
ans = ((ans + C.jz[1][1] * (n + 1) % m - C.jz[1][4]) % m + m) % m;//答案
printf ("%lld\n", ans);
return 0;
}