【题解】佳佳的斐波那契数列(矩阵)

【题解】佳佳的斐波那契数列

题目描述

求\(\Sigma i\times fib[i]\)的值

数据范围

\(n\le2^{31}-1\)

\(Solution\)

看数据范围就会做的题...
\[

\f(n):=ib[n]
\g(n)=nf(n)
\s(n)=\Sigma^{i\le n}_{i=1}g(n)
\]
然后
\[
f(i)=f(i-1)+f(i-2)
\s(i)=s(i-1)+g(i)
\]
不好求\(g\),但是可以直接这样
\[
g(i)=i\times f(i)\=i\times f(i-1)+i\times f(i-2)
\=(i-1)f(i-1)+(i-2)f(i-2)+f(i-1)+2f(i-2)
\=g(i-1)+g(i-2)+f(i-1)+2f(i-2)
\]
于是我们构造一个行向量(矩阵)
\[
k=\begin{pmatrix}
\g(i)&g(i+1)&f(i)&f(i+1)&s(i)&s(i+1)
\\\end{pmatrix}
\]
然后想办法构造一个转移矩阵
\[
k \times \begin{pmatrix}?\end{pmatrix}=\begin{pmatrix}
\g(i+1)&g(i+2)&f(i+1)&f(i+2)&s(i+1)&s(i+2)
\\\end{pmatrix}
\]
就直接根据转移式构造一下
\[
\begin{pmatrix}?\end{pmatrix}=
\begin{pmatrix}
0&1&0&0&0&1
\1&1&0&0&0&1
\0&2&0&1&0&2
\0&1&1&1&0&1
\0&0&0&0&0&0
\0&0&0&0&1&1
\end{pmatrix}
\]
初始矩阵是
\[
\begin{pmatrix}
\1&2&1&1&1&3
\\\end{pmatrix}
\]
最后直接取出第五列就好了(\(s(i)\))

#include<bits/stdc++.h>

using namespace std;typedef long long ll;
template < class ccf >
inline ccf qr(ccf b){
    register char c=getchar();register int q=1;register ccf x=0;
    while(c<48||c>57)q=c==45?-1:q,c=getchar();
    while(c>=48&&c<=57)x=x*10+c-48,c=getchar();
    return q==-1?-x:x;}
inline int qr(){return qr(1);}
int mod,n;
const int maxn=7;
struct MTX{
    int data[maxn][maxn];
    MTX(){
    for(register int t=1;t<=6;++t)
        for(register int i=1;i<=6;++i)
        data[t][i]=0;
    }
    inline int* operator [](register int x){return data[x];}
    inline void unis(){
    for(register int t=1;t<=6;++t)
        for(register int i=1;i<=6;++i)
        data[t][i]=0;
    for(register int t=1;t<=6;++t)
        data[t][t]=1;
    }

    inline void operator*=(MTX& f){
    MTX ret;
    for(register int k=1;k<=6;++k)
        for(register int t=1;t<=6;++t)
        for(register int i=1;i<=6;++i)
            ret[t][i]=(0ll+ret[t][i]+1ll*data[t][k]*f[k][i]%mod)%mod;
    *this=ret;
    }
    inline void operator ^=(const int&p){
    MTX base=*this,ret;ret.unis();
    for(register int t=p;t;base*=base,t>>=1)
        if(t&1) ret*=base;
    *this=ret;
    }
}yyb;
ll vec[7]={0,1,2,1,1,1,3};

int main(){
    freopen("fib.in","r",stdin);
    freopen("fib.out","w",stdout);
    n=qr();mod=qr();
    if(n<=2){
    if(n< 1) printf("%d\n",0);
    if(n==1) printf("%d\n",1%mod);
    if(n==2) printf("%d\n",3%mod);
    return 0;
    }

    yyb[1][1]=0;yyb[1][2]=1;yyb[1][3]=0;yyb[1][4]=0;yyb[1][5]=0;yyb[1][6]=1;
    yyb[2][1]=1;yyb[2][2]=1;yyb[2][3]=0;yyb[2][4]=0;yyb[2][5]=0;yyb[2][6]=1;
    yyb[3][1]=0;yyb[3][2]=2;yyb[3][3]=0;yyb[3][4]=1;yyb[3][5]=0;yyb[3][6]=2;
    yyb[4][1]=0;yyb[4][2]=1;yyb[4][3]=1;yyb[4][4]=1;yyb[4][5]=0;yyb[4][6]=1;
    yyb[5][1]=0;yyb[5][2]=0;yyb[5][3]=0;yyb[5][4]=0;yyb[5][5]=0;yyb[5][6]=0;
    yyb[6][1]=0;yyb[6][2]=0;yyb[6][3]=0;yyb[6][4]=0;yyb[6][5]=1;yyb[6][6]=1;

    yyb^=n-1;

    ll ans=0;
    for(register int t=1;t<=6;++t)
    ans=(ans+(vec[t]*yyb[t][5])%mod)%mod;
    printf("%lld\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/winlere/p/10805038.html

时间: 2024-10-09 00:54:38

【题解】佳佳的斐波那契数列(矩阵)的相关文章

HDU 4549 M斐波那契数列 ( 矩阵快速幂 + 费马小定理 )

HDU 4549 M斐波那契数列 (  矩阵快速幂 + 费马小定理  ) 题意:中文题,不解释 分析:最好的分析就是先推一推前几项,看看有什么规律 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef __int64 LL; #define CLR( a, b ) memset( a, b, sizeof(a) ) #define MOD 100000

HDU 4549 M斐波那契数列(矩阵快速幂&amp;费马小定理)

ps:今天和战友聊到矩阵快速幂,想到前几天学长推荐去刷矩阵专题,挑了其中唯一一道中文题,没想到越过山却被河挡住去路... 题目链接:[kuangbin带你飞]专题十九 矩阵 R - M斐波那契数列 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u 题意 Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2]

hdu4549---M斐波那契数列(矩阵+欧拉定理)

Problem Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a, b, n,你能求出F[n]的值吗? Input 输入包含多组测试数据: 每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 ) Output 对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模

hdu 4549 M斐波那契数列 矩阵快速幂+欧拉定理

M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Problem Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = aF[1] = bF[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a, b, n,你能求出F[n]的值吗? Input 输入包含多组测试数据:每组数据占一行,包含3个整数a, b,

斐波那契数列——矩阵的幂求解

题目: 斐波那契数列的递推公式如下: F(0) = 0; F(1) = 1; F(n + 2) = F(n + 1) + F(n); 求数列的第N项的值对10000取余的结果.( 0<=n<= 10^16) 求解斐波那契数列,如果N比较小的情况下,可以直接打表求解,但是对于N很大的情况下,并不适用. 所以,有些人会想到高精度计算,但是,N达到10^5以上时,时间复杂度难以想象,每计算一个数,需要进行高精度加法.然而还有求解对10000的取余的值. 我们可以用矩阵的幂来求解.斐波那契数列的递推公

[codevs]1250斐波那契数列&lt;矩阵dp&gt;

题目描述 Description 定义:f0=f1=1, fn=fn-1+fn-2(n>=2).{fi}称为Fibonacci数列. 输入n,求fn mod q.其中1<=q<=30000. 输入描述 Input Description 第一行一个数T(1<=T<=10000). 以下T行,每行两个数,n,q(n<=109, 1<=q<=30000) 输出描述 Output Description 文件包含T行,每行对应一个答案. 样例输入 Sample I

洛谷P1962 斐波那契数列 || P1349 广义斐波那契数列[矩阵乘法]

P1962 斐波那契数列 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 为整数) 题目描述 请你求出 f(n) mod 1000000007 的值. 输入输出格式 输入格式: ·第 1 行:一个整数 n 输出格式: 第 1 行: f(n) mod 1000000007 的值 输入输出样例 输入样例#1: 5 输出样例#1: 5 输入样例#2: 10 输出样例#2: 55 说明

UVA10299- Modular Fibonacci(斐波那契数列+矩阵快速幂)

题目链接 题意:给出n和m,求出f(n) % m, f(x)为斐波那契数列. 思路:因为n挺大的,如果直接利用公式计算很有可能会TLE,所以利用矩阵快速幂求解,|(1, 1), (1, 0)| * |f(n - 1), f(n - 2)| = |f(n), f(n - 1)|,所以求f(n)相当于|f(1), f(0)|乘上n - 1次的|(1, 1), (1, 0)|. 代码: #include <iostream> #include <cstdio> #include <

[ZJOI2011]细胞——斐波那契数列+矩阵加速+dp

Description bzoj2323 Solution 题目看起来非常复杂. 本质不同的细胞这个条件显然太啰嗦, 是否有些可以挖掘的性质? 1.发现,只要第一次分裂不同,那么互相之间一定是不同的(即使总数目相同). 所以先考虑第一次分裂后,一个固定小球体数量的情况: 2.第一次分裂后,最后的小球体数量固定.想要方案数不同,必须连接方式不同. 可以列出dp式子,f[n](以n结尾砍一刀)=f[n-2]+f[n-3]+...+f[2]+f[0],而f[0]=1,f[1]=0 而fibo[n]-1