题解 P6046 【纯粹容器】
dengyaotriangle · · 题解
显然,这题可以线性!
考虑一个点存活时间的期望
而我们看
显然,我们只需要考虑
那么,我们操作
考虑其中合法(即没有把
我们发现,
所以合法的方案数是
当然,由于这题数据范围小,直接用这个式子甚至都能过,我们继续化简
上式显然等于
拆开之后,易得,
(或者你用容斥原理也可以推出来上式,但是生成函数多方便)
那么
至此,这个问题可以
因为
我们发现这个和式是由4项形如
的东西组成的,而我们化简这个东西
注意上面的东西在
显然,我们可以线性预处理逆元求出这个式子,那么
所以总时间复杂度
#include<bits/stdc++.h>
using namespace std;
//dengyaotriangle!
const int maxn=55;
const int mdn=998244353;
int n;
int a[maxn];
int prv[maxn],nxt[maxn];
int inv[maxn];
int ans[maxn];
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n;
inv[1]=1;for(int i=2;i<=n;i++)inv[i]=inv[mdn%i]*(long long)(mdn-mdn/i)%mdn;
for(int i=0;i<n;i++)ans[i]=n*(long long)inv[i+1]%mdn;
for(int i=1;i<=n;i++)cin>>a[i];
stack<pair<int,int>> stk1,stk2;
for(int i=1;i<=n;i++)nxt[i]=n+1,prv[i]=0;
for(int i=1;i<=n;i++){
while(!stk1.empty()&&stk1.top().first<a[i]){nxt[stk1.top().second]=i;stk1.pop();}
stk1.push(make_pair(a[i],i));
}
for(int i=n;i>=1;i--){
while(!stk2.empty()&&stk2.top().first<a[i]){prv[stk2.top().second]=i;stk2.pop();}
stk2.push(make_pair(a[i],i));
}
for(int i=1;i<=n;i++){
vector<int> dis;
if(prv[i]!=0)dis.push_back(i-prv[i]);
if(nxt[i]!=n+1)dis.push_back(nxt[i]-i);
if(dis.empty())cout<<n-1<<' ';
else if(dis.size()==1){
int a=dis[0];
int w=(n-1ll-ans[a]+mdn)%mdn;
cout<<w<<' ';
}else{
int a=dis[0],b=dis[1];
int w=(n-1ll+mdn*2-ans[a]-ans[b]+ans[a+b])%mdn;
cout<<w<<' ';
}
}
return 0;
}