【JZOJ 4938】 序列 70分做法

本文介绍了一种使用动态规划(DP)方法解决特定数学期望值问题的方法。通过定义状态转移方程并利用辅助数组,作者实现了O(n^2)的时间复杂度。代码中详细展示了如何计算一系列数字的平方和的期望值。

Description

这里写图片描述
这里写图片描述

Analysis


如图,可能的状态转移
我比赛是想的辣鸡dp是从后往前,f[i][j]设dp到第i列,数为j的平方和的期望
为了求f,再设辅助数组g表示和的期望
那么转移显然,时间n^2

Code

我是个バカ我将中间运算过程记录成了分数实际上直接用逆元即可

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,b,a) for(int i=b;i>=a;i--)
using namespace std;
typedef long long ll;
const int N=2010;
const ll mo=998244353;
int n;
ll p[N];
struct frac
{
    ll x,y;
    frac(){x=0,y=1;}
}q,w,f[N][N],g[N][N];
ll gcd(ll x,ll y)
{
    if(x%y==0) return y;
    else return gcd(y,x%y);
}
frac make(ll a,ll b)
{
    frac t;t.x=a,t.y=b;
    return t;
}
frac add(frac a,frac b)
{
    frac c;
    c.y=a.y*b.y%mo,c.x=(a.x*b.y%mo+a.y*b.x%mo)%mo;
    return c;
}
frac add(frac a,ll b)
{
    frac c=make(b,1);
    return add(a,c);
}
frac mul(frac a,frac b)
{
    frac c;
    c.x=a.x*b.x%mo,c.y=a.y*b.y%mo;
    return c;
}
frac mul(ll k,frac b)
{
    frac a=make(k,1);
    return mul(a,b);
}
void exgcd(ll a,ll b,ll &x,ll &y)
{
    if(!b)
    {
        x=1,y=0;
        return;
    }
    ll x1,y1;
    exgcd(b,a%b,x1,y1);
    x=y1,y=x1-a/b*y1;
}
ll ny(ll a,ll b)
{
    ll x,y;
    exgcd(b,mo,x,y);
    x=(x%mo+mo)%mo;
    return a*x%mo;
}
int main()
{
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);
    scanf("%d",&n);
    fo(i,1,n) scanf("%lld",&p[i]);
    fo(i,0,n) f[n][i].x=i*i,g[n][i].x=i,f[n][i].y=g[n][i].y=1;
    fd(i,n-1,0)
    {
        q.x=p[i+1],q.y=100;
        w.x=100-p[i+1],w.y=100;
        fo(j,0,i)
        {
            frac x=add(g[i+1][0],j);
            g[i][j]=mul(w,x);
            x=add(g[i+1][j+1],j);
            g[i][j]=add(g[i][j],mul(q,x));

            x=add(mul(2*j,g[i+1][0]),j*j);
            f[i][j]=mul(w,add(f[i+1][0],x));

            x=add(mul(2*j,g[i+1][j+1]),j*j);
            f[i][j]=add(f[i][j],mul(q,add(f[i+1][j+1],x)));
        }
    }
    printf("%lld",ny(f[0][0].x,f[0][0].y));
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值