斐波

题目描述

题解

首先设\(f(S)=\sum_{T\subseteq S}g(\sum_{t\in T}t),g(n)=fib(n)^2\)
一个性质:
\(h(n)=f(n)*g(n)\),若\(f(n),g(n)\)都为线性递推式,则\(h(n)\)也为线性递推式

那么
\(fib(n)^2=[fib(n-1)+fib(n-2)]^2=fib(n-1)^2+fib(n-2)^2+2fib(n-1)fib(n-2)\)
\(2fib(n-1)fib(n-2)=fib(n-2)^2+fib(n-3)fib(n-2)+fib(n-1)[fib(n-1)-fib(n-3)]\)
\(\quad\quad\quad\quad\quad\quad\quad\quad\: =fib(n-2)^2+fib(n-1)^2+fib(n-3)fib(n-2)-fib(n-1)fib(n-3)\)
\(\quad\quad\quad\quad\quad\quad\quad\quad\: =fib(n-2)^2+fib(n-1)^2-fib(n-3)^2\)

\(fib(n)^2=2fib(n-1)^2+2fib(n-2)^2-fib(n-3)^2\)
\(g(n)=2g(n-1)+2g(n-2)-g(n-3)\)

\[令G(n)=\begin{pmatrix} g(n)\\g(n-1)\\g(n-2) \end{pmatrix} =\begin{pmatrix} 2&2&-1\\ 1&0&0\\ 0&1&0 \end{pmatrix}* \begin{pmatrix} g(n-1)\\g(n-2)\\g(n-3) \end{pmatrix}=A^n* \begin{pmatrix} 0\\1\\1 \end{pmatrix}\]

\(F(S)=\sum_{T\subseteq S}G(\sum_{t\in T}t)\)

考虑集合S新加个数{a}
\(F(S \bigcup \{a\})=F(S)+\sum_{T\subseteq S}G(a+\sum_{t\in T}t)=(I+A^a)F(S)(I为单位矩阵)\)

因此\(F(S)=G(0)\cdot\prod_{s\in S}(I+A^s)\)

所以\(\sum_{i=l}^{r}\sum_{j=i}^{r}f(\{a_i,a_{i+1},···,a_j\})=G(0)\sum_{i=l}^{r}\sum_{j=i}^{r}\prod_{k=i}^j(I+A^{a_k})\)

这样就转化为了线段树的问题
首先考虑如何求\(T(l,r)=\sum_{i=l}^{r}\sum_{j=i}^{r}\prod_{k=i}^j(I+A^{a_k})\)
可以考虑分治的思想
image
先分别求出T(L,M)和T(M+1,R)
再求出贯穿M的区间答案
\(S_l(l,r)=\sum_{i=l}^r\prod_{j=l}^i(I+A^{a_j}),S_r(i,j)=\sum_{i=l}^r\prod_{j=i}^r(I+A^{a_j})\)
\(T(l,r)=T(l,M)+T(M+1,r)+S_r(l,M)*S_l(M+1,r)\)
\(S_t(l,r)=\prod_{i=l}^r(I+A^{a_i})\)
\(S_r(l,r)=S_r(M+1,r)+S_r(l,M)*S_t(M+1,r),S_l(l,r)=S_l(l,M)+S_l(M+1,r)*S_t(l,M),S_t(l,r)=S_t(l,M)*S_t(M+1,r)\)

那么我们可以用线段树,每个节点寸\(S_r,S_l,S_t,T\)的矩阵,合并的时候用上述式子即可

点击查看代码
#include<functional>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<deque>
#define ll long long 
using namespace std;
const int maxn=5e5+101;
const int MOD=998244353;
const int inf=2147483647;
ll read(){
    ll x=0,f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
    return x*f;
}
int n,m,a[maxn];
struct Matrix{
    ll a[3][3];
    void init(){
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++)a[i][j]=(i==j);
        }
    }
    void zero(){memset(a,0,sizeof(a));}
    Matrix operator*(const Matrix& m2)const{
        Matrix m;m.zero();
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                for(int k=0;k<3;k++){
                    (m.a[i][j]+=a[i][k]*m2.a[k][j]%MOD)%=MOD;
                }
            }
        }
        return m;
    }
    Matrix operator+(const Matrix& m2)const{
        Matrix m;m.zero();
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                (m.a[i][j]+=(a[i][j]+m2.a[i][j])%MOD)%=MOD;
            }
        }
        return m;
    }
    Matrix operator^(ll y)const{
        Matrix sum,x;sum.init();
        memcpy(x.a,a,sizeof(a));
        while(y){
            if(y&1)sum=sum*x;
            y>>=1;x=x*x;
        }
        return sum;
    }
}A,G;
struct tree{
    Matrix M,sr,sl,st;
    void init(){
        M.init();sr.init();sl.init();st.init();
    }
}tr[maxn];
void build(int k,int l,int r){
    tr[k].init();
    if(l==r){   
        Matrix ss;ss.init();
        tr[k].M=tr[k].sr=tr[k].sl=tr[k].st=ss+(A^a[l]);//注意括号
        return ;
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    tr[k].M=(tr[k<<1].M+tr[k<<1|1].M)+(tr[k<<1].sr*tr[k<<1|1].sl);
    tr[k].st=tr[k<<1].st*tr[k<<1|1].st;
    tr[k].sl=tr[k<<1].sl+(tr[k<<1].st*tr[k<<1|1].sl);
    tr[k].sr=tr[k<<1|1].sr+(tr[k<<1|1].st*tr[k<<1].sr);
    return ;
}   
void update(int k,int l,int r,int L,int R,int v){
    if(r<L || l>R)return ;
    if(L<=l && r<=R){
        Matrix ss;ss.init();
        tr[k].M=tr[k].sr=tr[k].sl=tr[k].st=ss+(A^v);
        return ;
    }
    int mid=(l+r)>>1;
    update(k<<1,l,mid,L,R,v);update(k<<1|1,mid+1,r,L,R,v);
    tr[k].M=(tr[k<<1].M+tr[k<<1|1].M)+(tr[k<<1].sr*tr[k<<1|1].sl);
    tr[k].st=tr[k<<1].st*tr[k<<1|1].st;
    tr[k].sl=tr[k<<1].sl+(tr[k<<1].st*tr[k<<1|1].sl);
    tr[k].sr=tr[k<<1|1].sr+(tr[k<<1|1].st*tr[k<<1].sr);
    return ;
}
Matrix query(int k,int l,int r,int L,int R,bool &fa,Matrix &s1,Matrix &s2,Matrix &s3){
    Matrix ss;ss.zero();
    if(r<L || l>R){
        fa=0;
        return ss;
    }
    if(L<=l && r<=R){
        fa=1;
        s1=tr[k].sl;s2=tr[k].sr;s3=tr[k].st;
        return tr[k].M;
    }
    int mid=(l+r)>>1;
    Matrix sl1,sl2,sl3;
    Matrix sr1,sr2,sr3;
    Matrix aans;
    bool fa1=0,fa2=0;
    Matrix ans1=query(k<<1,l,mid,L,R,fa1,sl1,sl2,sl3);
    Matrix ans2=query(k<<1|1,mid+1,r,L,R,fa2,sr1,sr2,sr3);
    aans=ans1+ans2;
    if(fa1 && fa2){
        fa=1;
        aans=aans+(sl2*sr1);
        s1=sl1+(sl3*sr1);
        s2=sr2+(sr3*sl2);
        s3=sl3*sr3;
    }
    else if(fa1){
        fa=1;
        s1=sl1;s2=sl2;s3=sl3;
    }
    else {
        fa=1;
        s1=sr1;s2=sr2;s3=sr3;
    }
    return aans;
}
int main(){
    A.a[0][0]=A.a[0][1]=2;A.a[0][2]=-1;
    A.a[1][0]=1;A.a[1][1]=A.a[1][2]=0;
    A.a[2][0]=A.a[2][2]=0;A.a[2][1]=1;
    G.a[0][0]=0;G.a[1][0]=G.a[2][0]=1;
    n=read();m=read();for(int i=1;i<=n;i++)a[i]=read();build(1,1,n);
    for(int i=1;i<=m;i++){
        int opt=read(),l=read(),r=read();
        if(opt==1)update(1,1,n,l,l,r);
        else {
            bool fa;
            Matrix s1,s2,st,ss=query(1,1,n,l,r,fa,s1,s2,st);ss=ss*G;
            printf("%lld\n",(ss.a[0][0]%MOD+MOD)%MOD);
        }
    }
    return 0;
}
posted @ 2021-11-18 22:20  I_N_V  阅读(296)  评论(0编辑  收藏  举报