掷骰子题解(期望DP)

题目描述

一行有NNN个格子,编号为1,2,…,N1,2,\dots,N1,2,,N,你站在格子111处。前N−1N-1N1个格子中,每个格子中都有一枚特殊的骰子。第iii个格子上的骰子,标有0,1,…,Ai0,1,\dots,A_i0,1,,Ai这些数。你每到一个格子,就会掷一次骰子,如果骰子掷出为yyy,你当前在iii号格子,那么你可以跳到第i+yi+yi+y号格子。骰子上的每一个数都是等概率出现的。问你走到第NNN个格子时,期望要丢多少次骰子?答案对998244353998244353998244353取模。对期望的取模的操作为:期望是一个分数,你先化简分数,分子乘上分母关于998244353998244353998244353的逆元,得到一个整数,输出该整数。

输入格式

第一行输出nnn。第二行有n−1n-1n1个数,为A1,A2,…,An−1A_1,A_2,\dots,A_{n-1}A1,A2,,An1

输出格式

输出答案

输入样例1
3
1 1
输出样例1
4
输出样例2
5
3 1 2 1
输出样例2
332748122
数据范围

2≤N≤2∗105,1≤Ai≤N−i(1≤i≤N−1)2\leq N\leq 2*10^5,1\leq A_i\leq N-i(1\leq i\leq N-1)2N2105,1AiNi(1iN1)

题解

这是一道期望DP,设fif_ifi表示走到第iii个格子时期望要走多少次才能到第NNN个格子,fN=0f_N=0fN=0,可以列出转移式:

fi=∑j=ii+AifjAi+1+1f_i=\frac{\sum\limits_{j=i}^{i+A_i}f_j}{A_i+1}+1fi=Ai+1j=ii+Aifj+1

在第iii个格子,等概率到第iiii+Aii+A_ii+Ai个格子。但是,观察可得,fif_ifi的转移式是包括fif_ifi本身的,所以我们需要做一些调整。两边同时减去fiAi+1\frac{f_i}{A_i+1}Ai+1fi

AiAi+1fi=∑j=i+1i+AifjAi+1+1\frac{A_i}{A_i+1}f_i=\frac{\sum\limits_{j=i+1}^{i+A_i}f_j}{A_i+1}+1Ai+1Aifi=Ai+1j=i+1i+Aifj+1

两边同时乘Ai+1Ai\frac{A_i+1}{A_i}AiAi+1

fi=∑j=i+1i+AifjAi+Ai+1Aif_i=\frac{\sum\limits_{j=i+1}^{i+A_i}f_j}{A_i}+\frac{A_i+1}{A_i}fi=Aij=i+1i+Aifj+AiAi+1

用前缀和维护fff数组,即可线性求解。

code

#include<bits/stdc++.h>
using namespace std;
int n;
long long mod=998244353,a[200005],f[200005],sum[200005];
long long mi(long long t,long long v){
    if(v==0) return 1;
    long long re=mi(t,v/2);
    re=re*re%mod;
    if(v&1) re=re*t%mod;
    return re;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        scanf("%lld",&a[i]);
    }
    for(int i=n-1;i>=1;i--){
        f[i]=(sum[i+1]-sum[i+a[i]+1]+mod)%mod;
        f[i]=(f[i]+a[i]+1)%mod;
        f[i]=f[i]*mi(a[i],mod-2)%mod;
        sum[i]=(sum[i+1]+f[i])%mod;
    }
    printf("%lld",f[1]);
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值