原题题面:https://ac.nowcoder.com/acm/contest/33194/B
分析:
第一眼,便能看出这道题是动态规划
可设
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]为当前位置为
i
i
i,走了
j
j
j步时到达点1的概率
因此对于每一个在1到a[i]范围内的
k
k
k
d p [ i + k ] [ j + 1 ] + = d p [ i ] [ j ] ∗ 1 a [ i ] dp[i+k][j+1]+=dp[i][j]*\frac{1}{a[i]} dp[i+k][j+1]+=dp[i][j]∗a[i]1
可是,此刻时间复杂度为O
(
N
3
)
(N^3)
(N3),显然无法通过这道题
观察式子,可以发现
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]加了很多次,故可以考虑用差分来解决
d
p
[
i
+
1
]
[
j
+
1
]
+
=
d
p
[
i
]
[
j
]
∗
1
a
[
i
]
dp[i+1][j+1]+=dp[i][j]*\frac{1}{a[i]}
dp[i+1][j+1]+=dp[i][j]∗a[i]1
d
p
[
i
+
1
+
a
[
i
]
]
[
j
+
1
]
−
=
d
p
[
i
]
[
j
]
∗
1
a
[
i
]
dp[i+1+a[i]][j+1]-=dp[i][j]*\frac{1}{a[i]}
dp[i+1+a[i]][j+1]−=dp[i][j]∗a[i]1
最后再用前缀和再加一遍
综上,时间复杂度便为
O
(
n
2
)
O(n^2)
O(n2),可以通过此题
***
代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int mod=998244353;
const int MXN=8007;
int a[MXN],dp[MXN][MXN],ifac[MXN],sum[MXN][MXN];
int qpow(int x,int times){
int ret=1,tmp=x;
while(times){
if(times&1) ret=1ll*ret*tmp%mod;
tmp=1ll*tmp*tmp%mod;
times>>=1;
}
return ret%mod;
}
int main(){
int n;
LL res=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
ifac[i]=qpow(i,mod-2);
}
for(int i=1;i<n;i++){
scanf("%d",&a[i]);
}
dp[n][0]=1;
for(int i=1;i<=n;i++){
sum[i][0]=1;
}
for(int i=n-1;i>=1;i--){
for(int j=1;j<=n-i;j++){
dp[i][j]=1ll*(dp[i][j]+sum[i+1][j-1]-sum[i+a[i]+1][j-1])*1ll*ifac[a[i]]%mod;
sum[i][j]=1ll*(sum[i+1][j]+dp[i][j])%mod;
}
}
for(int i=1;i<=n;i++){
res=(res+1ll*dp[1][i]*dp[1][i])%mod;
}
printf("%lld\n",res);
}