zoukankan      html  css  js  c++  java
  • 并不对劲的uoj311.[UNR #2]积劳成疾

    题目大意

    (n)个数(b_1,...,b_n),一个数(m(mleq n))
    定义(n)个数(a_1,...,a_n)的价值是:(b_{max(a_1,...,a_m)} imes b_{max(a_2,...,a_{m+1})} imes... imes b_{max(a_{n-m+1},...,a_n)})
    (a_1,...,a_n)中每个数在(1,2,3,...,n)中均匀随机,求价值的期望( imes n^n)模998244353。
    (1leq mleq nleq 400;b_i<998244353)

    题解

    价值的期望( imes n^n)等于(a_1,...,a_n)的所有不同取值方案的价值之和。
    可以设(f(l,r,k))表示(a_l,...,a_r)这一段中最大值为(k)时,所有(a_l,...,a_r)的不同取值方案的价值之和。
    转移时枚举(a_l,...,a_r)中最大值出现的第一个(或最后一个)位置,递归计算左右两边,再计算这个最大值对答案的贡献。
    (f(l,r,k))时,当最大值出现在位置(x(l< xleq r))时,需要先算出(f(l,x-1,1)+...+f(l,x-1,k-1))。右边也是。
    这样总时间复杂度是 (状态数 imes转移时间=Theta(n^3 imes n^2)=Theta(n^5)),空间复杂度是(Theta(n^3)),看上去都过不了。
    (f(l,x-1,1)+...+f(l,x-1,k-1))可以前缀和优化。
    发现区间相同时,区间端点具体在哪不影响(f(l,r,k)),只有区间长度影响(f(l,r,k))。把前两维变成一维。
    这样时间复杂度就是(Theta(n^3))

    代码
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<iomanip>
    #include<iostream>
    #include<map>
    #include<queue>
    #include<stack>
    #include<vector>
    #define LL long long
    #define rep(i,x,y) for(int i=(x);i<=(y);++i)
    #define dwn(i,x,y) for(int i=(x);i>=(y);--i)
    #define view(u,k) for(int k=fir[u];~k;k=nxt[k])
    #define maxn 401
    using namespace std;
    int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)&&ch!='-')ch=getchar();
    	if(ch=='-')f=-1,ch=getchar();
    	while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return x*f;
    }
    void write(int x)
    {
    	char ch[20];int f=0;
    	if(!x){putchar('0'),putchar('
    ');return;}
    	if(x<0)putchar('-'),x=-x;
    	while(x)ch[++f]=x%10+'0',x/=10;
    	while(f)putchar(ch[f--]);
    	putchar('
    ');
    }
    const LL mod=998244353;
    int n,K,f[maxn][maxn],g[maxn][maxn],w[maxn],pw[maxn][maxn],pw2[maxn][maxn];
    inline int mo(int x){return x>=mod?x-mod:x;}
    inline int calc(int len,int p,int x)
    {
    	if(len<K)return 1;
    	return pw[x][min(len-K+1,p)-max(p-K+1,1)+1];
    }
    void work(int len,int k)
    {
    	if(f[len][k]!=-1)return;
    	if(len<K){f[len][k]=g[len][k]=pw2[k][len];return;} 
    	f[len][k]=0;
    	for(int i=1;i<=len;i++)
    	{
    		if(i!=len&&k==1)continue;
    		int tmp=1;
    		if(i>1)work(i-1,k),tmp=g[i-1][k];
    		if(i<len)work(len-i,k-1),tmp=(LL)tmp*g[len-i][k-1]%mod;
    		f[len][k]=mo(f[len][k]+(LL)calc(len,i,k)*tmp%mod);
    	}
    	work(len,k-1);g[len][k]=mo(f[len][k]+g[len][k-1]);
    	return;
    }
    int main()
    {
    	n=read(),K=read();
    	rep(i,1,n){w[i]=read();pw[i][0]=pw2[i][0]=1;rep(j,1,n)pw2[i][j]=(LL)pw2[i][j-1]*i%mod,pw[i][j]=(LL)pw[i][j-1]*w[i]%mod;}
    	rep(l,1,n)rep(k,1,n)f[l][k]=-1;
    	work(n,n);
    	write(g[n][n]);
    	return (~(0-0)+1);
    }
    
  • 相关阅读:
    Java虚拟机JVM学习05 类加载器的父委托机制
    java 接口
    java 抽象类
    代码块(2)
    获取超额收益的思考
    HttpServer
    交易过程思考
    A股时间窗口
    redash学习记录
    MySQL学习记录
  • 原文地址:https://www.cnblogs.com/xzyf/p/12893098.html
Copyright © 2011-2022 走看看