zoukankan      html  css  js  c++  java
  • UOJ #311「UNR #2」积劳成疾

    需要锻炼$ DP$能力

    UOJ #311


    题意

    等概率产生一个长度为$ n$且每个数在[1,n]间随机的数列

    定义其价值为所有长度为$ k$的连续子数列的最大值的乘积

    给定$ n,k$求所有合法数列的价值和


    题解

    设$ f(x,y)$表示长度为$x$的数列中,最值不超过$ y$的所有数列的价值和

    若数列的最值不是$ y$则$ f(x,y)=f(x,y-1)$

    否则枚举最左边的最值位置,设为位置$ i$

    则$ f(x,y)$可由$f(i-1,y-1)·w(y)^{calc(i)}·f(x-i,y)$转移过来

    其中$ calc(i)$表示在长度为$ x$的数列中有多少个长度为$ k$的数列包含第$ i$个位置

    时间复杂度$ O(n^3)$


    代码

    #include<ctime>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #define p 998244353
    #define rt register int
    #define ll long long
    using namespace std;
    inline ll read(){
        ll x=0;char zf=1;char ch=getchar();
        while(ch!='-'&&!isdigit(ch))ch=getchar();
        if(ch=='-')zf=-1,ch=getchar();
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();return x*zf;
    }
    void write(ll y){if(y<0)putchar('-'),y=-y;if(y>9)write(y/10);putchar(y%10+48);}
    void writeln(const ll y){write(y);putchar('
    ');}
    int k,m,n,x,y,z,cnt,ans;
    int w[405];
    int calc(int x,int y){
        int L=max(1,x-m+1),R=min(x,y-m+1);
        return max(0,R-L+1);
    }
    int f[405][405],mi[405][405];
    int main(){
        n=read();m=read();
        for(rt i=1;i<=n;i++)w[i]=read();
        for(rt i=0;i<=n;i++)f[0][i]=1;
        for(rt i=1;i<=n;i++){
            mi[i][0]=1;
            for(rt j=1;j<=n;j++)mi[i][j]=1ll*mi[i][j-1]*w[i]%p;
        }
        for(rt i=1;i<=n;i++)
        for(rt j=1;j<=n;j++){
            if(j>1)f[i][j]=f[i][j-1];
            for(rt k=1;k<=i;k++)(f[i][j]+=1ll*f[k-1][j-1]*f[i-k][j]%p*mi[j][calc(k,i)]%p)%=p;
        }
        cout<<f[n][n];
        return 0;
    }
  • 相关阅读:
    JS 面向对象
    堆 栈
    考试题
    HTML Meta标签
    Nodejs 安装
    CSS3 背景图片的大小位置
    JS Math函数
    CSS3 巧用before after选择器
    计算机网络原理_数据链路层
    Asp.net_验证控件
  • 原文地址:https://www.cnblogs.com/DreamlessDreams/p/10249373.html
Copyright © 2011-2022 走看看