考虑用\(DP\)和组合数学来解决。

因为原图像不规则的形状不好处理,所以先用笛卡尔树(性质为小根堆)将其划分成一个一个的矩形。

发现在笛卡尔树上的每个节点都对应一个矩形,矩形高为\(h_x-h_{fa_x}\),宽为\(size_x\)。

结合笛卡尔树的性质,不难得到,红色矩形所对应的节点的两个儿子为绿色矩形和蓝色矩形。

设\(f_{x,i}\)为在节点\(x\)所对应的矩形及其以上的图形中放\(i\)个点的方案数,那么答案为\(f_{root,k}\)

与子树合并时只需枚举在子树图像中放的点个数,再用乘法原理乘起来。

再考虑其本身的矩形。

若是在一个\(n \times m\)的矩形中放\(k\)个点,其方案数为\(C_{n}^kC_{m}^kk!\),因为你需要从\(n\)行中选\(k\)行,从\(m\)列中选\(k\)列,同时这些选择的顺序可以改变,所以再乘上\(k!\)。

那么再考虑本身的矩形时,枚举在自身的矩形中放的点个数,再乘上\(C_{n}^kC_{m}^kk!\)即可

实现细节就看代码吧。

\(code:\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define maxn 5010
#define mod 1000000007
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
ll n,k,top,root;
ll ls[maxn],rs[maxn],st[maxn];
ll f[maxn][maxn],h[maxn],siz[maxn],fac[1000050],inv[1000050];
ll qp(ll x,ll y)
{
ll ans=1;
while(y)
{
if(y&1) ans=(ans*x)%mod;
x=(x*x)%mod;
y>>=1;
}
return ans%mod;
}
void init()
{
fac[0]=fac[1]=inv[0]=inv[1]=1;
fac[2]=2,inv[2]=qp(2,mod-2);
for(int i=3;i<=1000000;++i)
{
fac[i]=(fac[i-1]*i)%mod;
inv[i]=qp(fac[i],mod-2);
}
}
ll C(ll n,ll m)
{
if(n<m) return 0;
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int build()
{
for(int i=1;i<=n;++i)
{
while(top&&h[st[top]]>h[i]) ls[i]=st[top--];
if(top) rs[st[top]]=i;
st[++top]=i;
}
return st[1];
}
void dfs(int x,int val)
{
f[x][0]=siz[x]=1;
ll high=h[x]-val;
if(ls[x])
{
ll y=ls[x];
dfs(y,h[x]),siz[x]+=siz[y];
for(ll i=min(siz[x],k);i>=0;--i)
for(ll j=1;j<=min(siz[y],i);++j)
f[x][i]=(f[x][i]+f[y][j]*f[x][i-j]%mod)%mod;
}
if(rs[x])
{
ll y=rs[x];
dfs(y,h[x]),siz[x]+=siz[y];
for(ll i=min(siz[x],k);i>=0;--i)
for(ll j=1;j<=min(siz[y],i);++j)
f[x][i]=(f[x][i]+f[y][j]*f[x][i-j]%mod)%mod;
}
for(ll i=min(siz[x],k);i>=0;--i)
for(ll j=1;j<=min(high,i);++j)
f[x][i]=(f[x][i]+f[x][i-j]*fac[j]%mod*C(high,j)%mod*C(siz[x]-(i-j),j)%mod)%mod;
}
int main()
{
init();
read(n),read(k);
for(int i=1;i<=n;++i) read(h[i]);
root=build();
dfs(root,0);
printf("%lld",f[root][k]);
return 0;
}

最新文章

  1. 基于Ruby的watir-webdriver自动化测试方案与实施(五)
  2. canvas简单处理图片(反色处理)
  3. Entity Framework基础01
  4. a c lang in linux
  5. [转]Linux下权限掩码umask
  6. 新浪微博登陆,获取token
  7. 仅当使用了列的列表并且 IDENTITY_INSERT 为 ON 时,才能为表&#39;SpeType&#39;中的标识列指定显式值
  8. androik_sdk 更新慢问题解决办法。
  9. win8vs2012创建自带sqlServer数据库出错
  10. Oracle\MS SQL Server Update多表关联更新
  11. 我的iOS-App
  12. 20162328蔡文琛week07
  13. zabbix微信报警信息优化模板
  14. hdu-4825(01字典树)
  15. [c/c++] programming之路(7)、数据类型转换、偷钱小程序、进制转换
  16. Codeforces 675E Trains and Statistic - 线段树 - 动态规划
  17. qualcomm lk gpio
  18. Control(拆点+最大流)
  19. web文件上传组件比较jQuery File Upload和Fine Uploader
  20. 170609、Nginx配置文件详细说明

热门文章

  1. java android 序列号serializable和parcelable
  2. 慕课网 性能优化之MySQL优化--- max 和count的性能优化
  3. vue全家桶(2.5)
  4. js事件入门(1)
  5. 全栈的自我修养: 001环境搭建 (使用Vue,Spring Boot,Flask,Django 完成Vue前后端分离开发)
  6. .net Core中如何读取Appsetting配置文件
  7. 一.1搭建跨平台的统一python开发环境
  8. 集成Swagger在线调试
  9. excel把按行合并的单元格重新拆分
  10. css如何让文字不换行显示?