zoukankan      html  css  js  c++  java
  • 2020/11/03 模拟赛 斐波

    Description

    假设$fib(n)$为斐波那契数列的第 $n$ 项,其中$fib(0)=0,fib(1)=1$,且$fib(n)=fib(n-1)+fib(n-2),(n > 1)$。 假设$S$是一个可重集合${ s_1,s_2,cdots ,a_{|S|}$,$f(S)$ 定义为$f(S)=sum_{T subseteq S}[fib(sum_{s in T}s)]$ 有一个数组$a_1,a_2, cdots ,a_n$,牛妹会对数组进行$q$次操作,每次操作可能是以下两种 操作中的一种: 1. 把$a_p$变为$v$; 2. 计算 $sum_{i=l}^r sum_{j=i}^r f({ a_i,a_{i+1},cdots,a_j)})$。 对于每个操作 2,输出答案模 $998244353$。

    Solution

    题目要求求出下式的值并支持修改操作:

    $$sum_{i=l}^r sum_{j=i}^r f( {a_i,a_{i+1}, cdots ,a_j })$$

    其中$f(S)=sum_{T subseteq S}[fib(sum_{s in T}s)]$

    设$g(n)=fib^2(n)$也可以递推,递推公式为$g(n)=2g(n-1)+2g(n-2)-g(n-3)$(证明方法:使用通项公式硬算)

    可以用矩阵写出:

    $$egin{pmatrix}
    g(n)\
    g(n-1)\
    g(n-2)
    end{pmatrix}
    =
    egin{pmatrix}
    2 & 2 & -1\
    1 & 0 & 0\
    0 & 1 & 0
    end{pmatrix}
    egin{pmatrix}
    g(n-1) \
    g(n-2) \
    g(n-3)
    end{pmatrix}$$

    然后换成向量:

    $$vec{g_n}=Avec{g_{n-1}}=A^nvec{g_0}$$

    那么$vec{f(S)}=sum_{T subseteq S}vec{g_{sum T}}$

    考虑向$S$中加入一个数$a$,可以得到$vec{f(S cup {a})} = vec{f(S)} + sum_{T subseteq S}vec{g_{sum T +a}} = vec{f(S)} + A^a vec{g_{sum T}} = (A^a + 1) vec{f(S)}$

    $1$表示单位矩阵

    设$S={a_1,a_2, cdots ,a_n }$,那么$vec{f(S)}= prod_{i=1}^n (1+A^{a_i})vec{g_0}$

    设$B_i=1+A^{a_i}$,那么题中所求即为$sum_{i=l}^r sum_{j=i}^r prod_{k=i}^j B_k$

    用线段树维护即可

    常数特别难卡

    #pragma GCC optimize(2)
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    int n,q;
    const long long mod=998244353;
    struct Matrix
    {
        int a[3][3];
        inline void clear()
        {
            memset(a,0,sizeof(a));
        }
        Matrix operator + (Matrix z)const
        {
            for(register int i=0;i<3;i++) for(register int j=0;j<3;j++) (z.a[i][j]+=this->a[i][j])<mod?0:z.a[i][j]-=mod;
            return z;
        }
        Matrix operator * (const Matrix &z)const
        {
            return (Matrix){
                (a[0][0]*1ll*z.a[0][0]+a[0][1]*1ll*z.a[1][0]+a[0][2]*1ll*z.a[2][0])%mod,
                (a[0][0]*1ll*z.a[0][1]+a[0][1]*1ll*z.a[1][1]+a[0][2]*1ll*z.a[2][1])%mod,
                (a[0][0]*1ll*z.a[0][2]+a[0][1]*1ll*z.a[1][2]+a[0][2]*1ll*z.a[2][2])%mod,
                (a[1][0]*1ll*z.a[0][0]+a[1][1]*1ll*z.a[1][0]+a[1][2]*1ll*z.a[2][0])%mod,
                (a[1][0]*1ll*z.a[0][1]+a[1][1]*1ll*z.a[1][1]+a[1][2]*1ll*z.a[2][1])%mod,
                (a[1][0]*1ll*z.a[0][2]+a[1][1]*1ll*z.a[1][2]+a[1][2]*1ll*z.a[2][2])%mod,
                (a[2][0]*1ll*z.a[0][0]+a[2][1]*1ll*z.a[1][0]+a[2][2]*1ll*z.a[2][0])%mod,
                (a[2][0]*1ll*z.a[0][1]+a[2][1]*1ll*z.a[1][1]+a[2][2]*1ll*z.a[2][1])%mod,
                (a[2][0]*1ll*z.a[0][2]+a[2][1]*1ll*z.a[1][2]+a[2][2]*1ll*z.a[2][2])%mod
            };
        }
        Matrix operator ^ (int z)const
        {
            Matrix ret,base;
            ret.clear();
            ret.a[0][0]=ret.a[1][1]=ret.a[2][2]=1;
            base=*this;
            while(z)
            {
                if(z&1) ret=ret*base;
                z>>=1;
                base=base*base;
            }
            return ret;
        }
    }M[100005],I,O,A;
    struct Tree
    {
        Matrix S,L,R,V;
        Tree operator + (Tree z)const
        {
            return (Tree){S+z.S+R*z.L,L+V*z.L,z.R+z.V*R,V*z.V};
        }
    }tree[400005];
    inline int read()
    {
        int w=0;
        char ch=0;
        while(ch<'0'||ch>'9') ch=getchar();
        while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
        return w;
    }
    void update(int i,int l,int r,int pos)
    {
        if(l==r)
        {
            tree[i].S=tree[i].L=tree[i].R=tree[i].V=M[l];return;
        }
        int mid=l+r>>1;
        if(pos<=mid) update(i<<1,l,mid,pos);
        else update(i<<1|1,mid+1,r,pos);
        tree[i]=tree[i<<1]+tree[i<<1|1];
    }
    Tree query(int i,int l,int r,int ll,int rr)
    {
        if(l>=ll&&r<=rr) return tree[i];
        int mid=l+r>>1;
        if(rr<=mid) return query(i<<1,l,mid,ll,rr);
        else if(ll>mid) return query(i<<1|1,mid+1,r,ll,rr);
        else return query(i<<1,l,mid,ll,rr)+query(i<<1|1,mid+1,r,ll,rr);
    }
    int main()
    {
        I.a[0][0]=I.a[1][1]=I.a[2][2]=1;
        O.a[1][0]=O.a[2][0]=1;
        A.a[0][0]=A.a[0][1]=2,A.a[0][2]=mod-1,A.a[1][0]=A.a[2][1]=1;
        n=read(),q=read();
        for(register int i=1;i<=n;i++) M[i]=(A^read())+I,update(1,1,n,i);
        for(register int i=1;i<=q;i++)
        {
            int opt=read();
            if(opt==1)
            {
                int p=read(),v=read();
                M[p]=(A^v)+I,update(1,1,n,p);
            }
            else
            {
                int l=read(),r=read();
                printf("%d
    ",((query(1,1,n,l,r).S*O).a[0][0]+mod)%mod);
            }
        }
        return 0;
    }
    斐波
  • 相关阅读:
    [Linux] crontab和shell每天定时备份数据库
    [Go] 实战项目在线客服GO-FLY -在gin框架使用IP识别库转换IP为城市
    [javascript] elementui和vue下复制粘贴上传图片
    [Go] GO-FLY客服项目被公众号 "转角遇到GitHub " 推荐
    [javascript] cdn模式下vue和vue-router实现路由
    [Go] Golang发送http GET请求
    [MySQL] 利用explain查看sql语句中使用的哪个索引
    [Go]GO语言实战-小程序或公众号接口gin框架验证微信服务器消息签名-开源WEB客服
    [Go]GO语言实战-开源WEB客服GO-FLY-gorm下分页的实现
    [前端] 设定为disabled的表单域值不能被提交
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13973518.html
Copyright © 2011-2022 走看看