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)$(证明方法:使用通项公式硬算)

可以用矩阵写出:

$$\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}$$

然后换成向量:

$$\vec{g_n}=A\vec{g_{n-1}}=A^n\vec{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$

用线段树维护即可

常数特别难卡

2020/11/03 模拟赛 斐波
#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\n",((query(1,1,n,l,r).S*O).a[0][0]+mod)%mod);
        }
    }
    return 0;
}
斐波

 

上一篇:深入理解Linux网络技术内幕 第32章 路由-Linux的实现


下一篇:fibnacci数列递归实现