“蔚来杯“2022牛客暑期多校训练营9 Two Frogs

原题题面: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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值