uoj311 【UNR #2】积劳成疾

传送门:http://uoj.ac/problem/311

【题解】

这题的期望dp好神奇啊(可能是我太菜了)

由于每个位置都完全一样,所以我们设$f_{i,j}$表示审了连续$i$个位置,最大值不超过$j$的期望。

那么只要考虑最大值为$j$的期望,其他从$f_{i,j-1}$加进来即可。

枚举最大值第一次出现的位置$p$(如果位置编号为$[1,i]$的话,因为位置都等价,所以可以这样做

然后考虑$p$一定对于这些区间有贡献$[\max(1, p-K+1), \min(i-K+1, p)]$,那么这些区间的价值都是$w_j$,乘起来即可。

然后前后两半互斥,分别转移即可。

设区间长度为$len$,也就是上面那坨减一下+1。

所以$f_{i,j} = f_{i,j-1} + \sum_{p=1}^i f_{p-1,j-1} * w_j^{len} * f_{i-p, j}$

考虑初始状态,连续$i$个位置最大值不超过$j$,其中$i < k$,也就是还没有组成一个完整的区间,那么根据上面的转移方程,这个区间的值完全由自己决定,也就是$f_{i,j} = j^i$。

复杂度$O(n^3)$

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 410 + 10;
const int mod = 998244353;

int n, K, w[M]; 
int f[M][M], c[M][M]; 
// 审了i套题,最大难度不超过j的方案数 
// f[i, j] = f[i, j-1] + \sum_{x=1}^{i} f[x-1, j-1] * f[n-x, j] * w[x]^p
 
inline int pwr(int a, int b) {
    int ret = 1;
    while(b) {
        if(b&1) ret = 1ll * ret * a % mod;
        a = 1ll * a * a % mod;
        b >>= 1;
    }
    return ret;
}
 
int main() {
    cin >> n >> K; 
    for (int i=1; i<=n; ++i) {
        scanf("%d", w+i);
        c[i][0] = 1; 
        for (int j=1; j<=n; ++j) c[i][j] = 1ll * c[i][j-1] * w[i] % mod; 
    }
    for (int i=0; i<=n; ++i) f[0][i] = 1;
    for (int i=1; i<=n; ++i) { 
        for (int j=1; j<=n; ++j) {
            if(i < K) f[i][j] = pwr(j, i); 
            else {
                f[i][j] = f[i][j-1]; 
                for (int x=1; x<=i; ++x) { 
                    f[i][j] = f[i][j] + 1ll * f[x-1][j-1] * f[i-x][j] % mod * c[j][min(i-K+1, x) - max(x-K+1, 1) + 1] % mod; 
                     if(f[i][j] >= mod) f[i][j] -= mod; 
                }
            }
        }
    }
    cout << f[n][n]; 

    return 0;
}
View Code

 

posted @ 2017-07-15 15:20  Galaxies  阅读(407)  评论(0编辑  收藏  举报