peiwenjun's blog 没有知识的荒原

CF1810G The Maximum Prefix 题解

题目描述

对于一个长度 \(\le n\) 的数组 \(a\)\(a_i\)\(p_i\) 概率为 \(1\) ,有 \(1-p_i\) 概率为 \(-1\)

定义 \(s_i=\sum_{j=1}^ia_j\)\(a\) 数组的最大前缀和为 \(S=\max_{i=0}^k s_i\)

给定 \(h_0,\cdots,h_n\) ,定义数组 \(a\) 的分数为 \(h_S\)

\(\forall 1\le k\le n\) ,求序列长度为 \(k\) 时,数组 \(a\) 的期望分数,对 \(10^9+7\) 取模。

数据范围

  • \(1\le n\le 5\cdot 10^3,0\le h_i\lt 10^9+7\)

时间限制 \(\texttt{1s}\) ,空间限制 \(\texttt{256MB}\)

分析

如果按照常规方法 \(\texttt{dp}\) ,我们需要记录当前前缀和与最大前缀和两个状态,时间复杂度 \(\mathcal O(n^3)\)

假设最大前缀和为 \(t\) ,原本的前缀和可以看成一条从 \((0,0)\) 开始,走到 \((k,?)\) 的折线,碰到的最大纵坐标为 \(t\)

将折线沿 \(y=\frac t2\) 翻转,那么会变成从 \((0,t)\) 出发,走到 \((k,?)\) ,要求碰到的最小纵坐标为 \(0\)

但是如果枚举 \(k\) 从右往左 \(\texttt{dp}\) ,时间复杂度仍然是 \(\mathcal O(n^3)\)

注意到我们不需要对每个 \(S\) 求出前缀和为 \(S\) 的概率,而只需要计算对 \(h_S\) 加权后的概率,所以我们可以在初始值上动手脚。

具体的,考虑从左往右 \(\texttt{dp}\) ,令 \(f_{i,j,0/1}\) 表示走到 \((i,j)\) ,是否已经碰到过 \(x=0\)加权贡献和

初始值 \(f_{0,S,[S=0]}=h_S\) ,转移乘上相应概率,在 \((k,?)\) 处统计答案。

时间复杂度 \(\mathcal O(n^2)\)

#include<bits/stdc++.h>
using namespace std;
const int maxn=5005,mod=1e9+7;
int n,t;
int p[maxn],q[maxn];
int f[maxn][maxn][2];
inline int qpow(int a,int k)
{
    int res=1;
    for(;k;a=1ll*a*a%mod,k>>=1) if(k&1) res=1ll*res*a%mod;
    return res;
}
inline void add(int &x,int y)
{
    if((x+=y)>=mod) x-=mod;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1,x=0,y=0;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            p[i]=1ll*x*qpow(y,mod-2)%mod,q[i]=mod+1-p[i];
        }
        for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) f[i][j][0]=f[i][j][1]=0;
        for(int i=0;i<=n;i++) scanf("%d",&f[0][i][i==0]);
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=n;j++)
                for(int k=0;k<=1;k++)
                {
                    if(j!=0) add(f[i][j-1][k|(j-1==0)],1ll*f[i-1][j][k]*p[i]%mod);
                    if(j!=n) add(f[i][j+1][k|(j+1==0)],1ll*f[i-1][j][k]*q[i]%mod);
                }
            int res=0;
            for(int j=0;j<=n;j++) add(res,f[i][j][1]);
            printf("%d ",res);
        }
        putchar('\n');
    }
    return 0;
}

posted on 2023-06-19 19:09  peiwenjun  阅读(5)  评论(0)    收藏  举报

导航