[BZOJ4574][UOJ#196][Zjoi2016][區間DP][概率]線段樹
阿新 • • 發佈:2019-01-02
#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 410
#define P 1000000007
using namespace std;
typedef long long ll;
int n,m;
int A[N],B[N],R[N];
ll cnt[N][N],sum[N][N];
ll f[2][N][N];
inline void rea(int &x){
char c=getchar(); x=0;
for(;c>'9'||c<'0';c=getchar());
for (;c>='0'&&c<='9';x=x*10+c-'0',c=getchar());
}
inline bool cmp(const int &a,const int &b){
return A[a]<A[b];
}
inline void solve(int l,int r,int x){
for(int i=l;i<=r;i++)
for(int j=l;j<=r;j++)
f[0][i][j]=f[1][i][j]=0;
f[0][l][r]=1;
for(int k=1;k<=m;k++){
for(int i=l;i<=r;i++){
ll w=0;
for(int j=r;j>=i;j--)
f[k&1][i][j]=w,w+=f[(k&1)^1][i][j]*(n-j);
}
for(ll j=l;j<=r;j++){
ll w=0;
for(int i=l;i<=j;i++)
f[k&1 ][i][j]=(f[k&1][i][j]+w)%P,w+=f[(k&1)^1][i][j]*(i-1);
}
for(int i=l;i<=r;i++)
for(int j=i;j<=r;j++)
f[k&1][i][j]=(f[k&1][i][j]+f[(k&1)^1][i][j]*cnt[i][j])%P;
}
for(ll i=l;i<=r;i++){
ll w=0;
for(int j=r;j>=i;j--){
w+=f[m&1][i][j];
sum[j][R[x]]=(sum[j][R[x]]+w)%P;
}
}
}
inline int calc(int x){
return x*(x+1)>>1;
}
int main(){
rea(n); rea(m);
for(int i=1;i<=n;i++) rea(A[i]),B[i]=i;
sort(B+1,B+1+n,cmp);
for(int i=1;i<=n;i++) R[B[i]]=i;
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++) cnt[i][j]=calc(i-1)+calc(n-j)+calc(j-i+1);
for(int i=1;i<=n;i++){
int l=i,r=i;
while(l&&A[i]>=A[l]) l--;
while(r<=n&&A[i]>=A[r]) r++;
solve(l+1,r-1,i);
}
for(int i=1;i<=n;i++){
ll Ans=0;
for(int j=1;j<=n;j++){
//printf("%lld ",sum[i][j]);
if(sum[i][j]==0) continue;
for(int k=1;k<j;k++) sum[i][j]=(sum[i][j]+P-sum[i][k])%P;
Ans=(Ans+1ll*A[B[j]]*sum[i][j])%P;
}
printf("%lld%c",Ans,i==n?'\n':' ');
}
}