$loj$10222 佳佳的$Fibonacci$ 矩阵快速幂

正解:矩阵快速幂

解题报告:

我永远喜欢loj!

一看到这个就应该能想到矩阵快速幂?

然后就考虑转移式,发现好像直接想不好想,,,主要的问题在于这个*$i$,就很不好搞$QAQ$

其实不难想到,$\sum_{i=1}^{n}a_i\cdot(n-i)$这样一个式子是可以在矩阵快速幂中推出来的(类似这个形式的都可,,,就随着编号递增系数递减这样子$QwQ$

具体来说就是表示成$\sum_{i=1}^{n}\sum_{j=1}^{i}a_j$,就欧克辣(具体实现后面港,,,

但是问题在于,它是$\sum_{i=1}^{n}a_i\cdot i$这样的,就随着编号递增系数递增这样子的$QwQ$

那显然就想到,变形嘛,就变成$\sum_{i=1}^{n}a_i\cdot n-\sum_{i=1}^{n}a_i\cdot(n-i)$这样子

然后就做完辣,,,?

剩下的就是考虑怎么表示出$\sum_{i=1}^{n}a_i$和$\sum_{i=1}^{n}a_i\cdot(n-i)$辣

对于第一个的话,可以考虑$\begin{bmatrix}\sum_{j=1}^{i-1} f_i \\ f_i\\ f_{i-1}\end{bmatrix}$$\cdot$$\begin{bmatrix}1 & 1 & 0\\ 0 & 1 & 1\\ 0 & 1 & 0\end{bmatrix}$,就欧克辣

然后第二个就差不多的方法,再加一维就好,$\begin{bmatrix}\sum _{j=1}^{i-1}\sum_{k=1}^{j}f_k\\ \sum_{j=1}^{i}f_j\\ f_{i+1}\\ f_{i}\end{bmatrix}$$\cdot$$\begin{bmatrix}1 & 1 & 0 & 0\\ 0 & 1 & 1 & 0\\ 0 & 0 & 1 & 1\\0 & 0 & 1 & 0\end{bmatrix}$

欧克做完辣,,,

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define int long long
#define gc getchar()
#define ri register int
#define rb register bool
#define rc register char
#define rp(i,x,y) for(ri i=x;i<=y;++i)

int n,mod;
struct matrix{int mat[5][5];il void clr(){memset(mat,0,sizeof(mat));}}e1,e2,fib;

il int read()
{
    rc ch=gc;ri x=0;rb y=1;
    while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
    if(ch=='-')ch=gc,y=0;
    while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
    return y?x:-x;
}
il matrix multi(matrix gd,matrix gs)
{
    matrix ret;ret.clr();
    rp(i,0,3)
        rp(j,0,3)
            rp(k,0,3)ret.mat[i][j]=(ret.mat[i][j]+gd.mat[i][k]*gs.mat[k][j]%mod)%mod;
    return ret;
}
il matrix power_1(ri x)
{matrix ret;ret.clr();ret.mat[0][1]=1;while(x){if(x&1)ret=multi(ret,e1);e1=multi(e1,e1);x>>=1;}return ret;}
il matrix power_2(ri x)
{matrix ret;ret.clr();ret.mat[0][2]=1;while(x){if(x&1)ret=multi(ret,e2);e2=multi(e2,e2);x>>=1;}return ret;}
namespace sub1
{
    il void main()
    {
        int fib1=1,fib2=1,as=0;
        rp(i,1,n){as=(as+1ll*fib1*i%mod)%mod;fib2+=fib1;fib1=fib2-fib1;if(fib2>=mod)fib2-=mod;}
        printf("%lld\n",as);
    }
}

main()
{
//    freopen("fib.in","r",stdin);freopen("fib.out","w",stdout);
    n=read();mod=read();
//    if(n<=100)return sub1::main(),0;
    e1.clr();e1.mat[0][0]=1;e1.mat[1][0]=1;e1.mat[1][1]=1;e1.mat[2][1]=1;e1.mat[1][2]=1;
    e2.clr();e2.mat[0][0]=1;e2.mat[1][0]=1;e2.mat[1][1]=1;e2.mat[2][1]=1;e2.mat[2][2]=1;e2.mat[3][2]=1;e2.mat[2][3]=1;
    matrix as1=power_1(n),as2=power_2(n);
    printf("%lld\n",((as1.mat[0][0]*n%mod-as2.mat[0][0])%mod+mod)%mod);
    return 0;
}
最后放下代码就好辣!(跑得飞慢,,,QAQ

猜你喜欢

转载自www.cnblogs.com/lqsukida/p/10805186.html