TR的数列(矩阵加速)

目录

一.题目

题目描述

输入

输出

样例输入

样例输出

提示

二.题解

三.代码

谢谢!


一.题目

题目描述

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

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

输入

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

1\leqslant n,m\leq 2^{31}-1

输出

Tn mod m的值

样例输入

5 5

样例输出

1

提示

样例解释:

T5 = (1*1+2*1+3*2+4*3+5*5)%5 = 46%5 = 1

二.题解

这道题可以说不难也不简单,有很多种方法,我这里只讲一种,感兴趣的可以把你的方法发给我哟!

这道题要求的是T_{n}=(1*f1+2*f2+3*f3+……+n*fn),于是我首先想到了构造一个4*4的矩阵,用[S_{n},f_{1}, f_{2},T_{n}]去乘它。但是发现无论如何都构造不出来。但是我可以构造出T1_{n}=(n*f1+(n-1)*f2+(n-2)*f3+……+1*fn),也就是

  *  [S_{n},f_{1}, f_{2},T_{n}](写错了,[1,4]=1)

但是这不是我们想要的结果,于是我又想,我们可以这样得到(1*f1+2*f2+3*f3+……+n*fn):

对于n = 5时:

得到这个矩阵:的和

减去Tn即答案。

递推式:T_{n}=S_{n}*(n+1)-T1_{n}

就这样就完了。

三.代码

#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;
}

谢谢!

发布了61 篇原创文章 · 获赞 32 · 访问量 8368

猜你喜欢

转载自blog.csdn.net/weixin_43908980/article/details/89018754