1. 程式人生 > >[BZOJ4574][UOJ#196][Zjoi2016][區間DP][概率]線段樹

[BZOJ4574][UOJ#196][Zjoi2016][區間DP][概率]線段樹

#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':' '); } }