A. 【UNR #2】积劳成疾
链接:http://uoj.ac/contest/40/problem/311
题解:
一道很好的期望题吧
用dp的老思路,枚举最大值将序列分割
想到这个就很简单了
状态f[i][j]表示前i个,最大值为j
f[i][j]=sigma(sigmaf[k][j-1]*sigmaf[i-k][j]*j^贡献次数)
然后显然这个可以前缀和优化一下
写代码莫名其妙写了+=mo
代码:
#include <bits/stdc++.h> using namespace std; #define N 500 #define mo 998244353 #define ll long long ll dp[N][N],js[N],w[N],n,m; int main() { freopen("noip.in","r",stdin); freopen("noip.out","w",stdout); std::ios::sync_with_stdio(false); cin>>n>>m; for (ll i=1;i<=n;i++) cin>>w[i]; for (ll i=0;i<=n;i++) dp[0][i]=1; for (ll i=1;i<=n;i++) { js[0]=1; for (ll j=1;j<=n;j++) js[j]=(js[j-1]*w[i])%mo; for (ll j=1;j<=n;j++) { dp[j][i]=dp[j][i-1]; for (ll k=1;k<=j;k++) dp[j][i]=(dp[j][i]+(dp[k-1][i-1]*dp[j-k][i])%mo*js[max(0ll,min(k,m)-max(k+m-j-1,0ll))])%mo; } } cout<<dp[n][n]%mo; return 0; }