并不对劲的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);
}
原文地址:https://www.cnblogs.com/xzyf/p/12893098.html