[DP] UOJ #311. 【UNR #2】积劳成疾

来源:互联网 发布:采购询价软件 编辑:程序博客网 时间:2024/06/05 02:50

fi,j表示长为 i 的区间 最大值是j 的答案
转移就枚举最左边的最大值在区间的位置 前缀和优化下就好了

好像也可以fi,j,k表示前 i 个,末尾 K 个中最大值在 j ,最大值是 k,有点复杂?

#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;#define read(x) scanf("%d",&(x))const int N=405;const int P=998244353;int n,K;int w[N];int f[N][N],g[N][N];inline void add(int &x,int y){  x+=y; if (x>=P) x-=P;}inline int calc(int i,int k){  return max(0,i-K+1)-max(0,k-1-K+1)-max(0,i-k-K+1);}inline ll Pow(ll a,int b){  ll ret=1;  for (;b;b>>=1,a=a*a%P)    if (b&1)      ret=ret*a%P;  return ret;}int pw[N][N];int tmp[N][N];int main(){  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  read(n); read(K);  for (int i=1;i<=n;i++) read(w[i]);  for (int i=0;i<=n;i++) f[0][i]=1;  for (int i=1;i<=n;i++)    for (int j=0;j<=n;j++)      pw[i][j]=Pow(w[i],j);  for (int i=1;i<=n;i++)    for (int j=1;j<=i;j++)      tmp[i][j]=calc(i,j);  for (int i=1;i<=n;i++){    for (int j=1;j<=n;j++)      for (int k=1;k<=i;k++)    add(f[i][j],(ll)f[k-1][j-1]*f[i-k][j]%P*pw[j][tmp[i][k]]%P);    for (int j=1;j<=n;j++)      add(f[i][j],f[i][j-1]);  }  printf("%d\n",f[n][n]);  return 0;}
原创粉丝点击