2020.7.4模拟 数据结构 (ds)
题目描述
wobmaj有N个数据结构,第i个数据结构具有工业指数Ai和包容指数Bi(Bi≤Ai)
他会不断执行下面这个操作,直到无法再执行为止:
选择二元组(i,j),将第i个数据结构套进第j个数据结构里,其中Ai<Bj。
每个数据结构只能嵌套和被嵌套一次。
求可能出现的不同局面的数量。答案对109+7取模。
N≤300,Bi<Ai<109
数据范围很小,DP可行。
因为Bi≤Ai,所以一个数据结构不能嵌套自己。
因为要执行到无法再执行为止,所以嵌套的数据结构数是固定并且最大的。
将一个数据结构拆成Ai,Bi两个点,从大到小排序,保证枚举到的Ai能被前面枚举的Bi嵌套。因为Ai=Bj时不能嵌套,所以相等时A在B前面。
设f[i][j][k]表示前i个点,有j个B点可选(没有嵌套A点)。
- 若第i个是B点,则方案数不变,可选的B点+1:
f[i][j+1][k]+=f[i−1][j][k]
- 若第i个是A点,则可以分三种情况讨论:
- 不嵌套:
如果Ai不被嵌套,那么Ai之前的所有B点必须在后面嵌套,否则,一定可以把Ai和前面的某一个B点嵌套,使得嵌套数量+1,说明当前的嵌套数没有达到最大。
设f[i][j][k]表示在j个可选的B点中,有k个是必选的(k≤j)。
所以,当前可选的j个点全部变为必选,方案数不变。
f[i][j][j]+=f[i−1][j][k]- 被非必选点嵌套:
f[i][j−1][k]+=f[i−1][j][k]∗(j−k)- 被必选点嵌套:
因为必选点被可选点包含,所以k−1的同时,也要j−1。
f[i][j−1][k−1]+=f[i−1][j][k]∗k - 不嵌套:
统计答案时,如果有必选点剩余则不合法。
最后答案即为n∑j=1f[n∗2][j][0]
用滚动数组可以消去第一维,不要忘记把f[i%2]清零。
代码如下
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#define MogeKo qwq
using namespace std;
const int maxn = 305;
const int mod = 1e9+7;
int n,x,y,cnt;
long long ans,f[2][maxn][maxn];
struct node {
int w,type;
bool operator < (const node &N)const {
return w > N.w || (w == N.w && type > N.type);
}
} d[maxn<<1];
int main() {
freopen("ds.in","r",stdin);
freopen("ds.out","w",stdout);
scanf("%d",&n);
for(int i = 1; i <= n; i++) {
scanf("%d%d",&x,&y);
d[++cnt] = (node) {x,1};
d[++cnt] = (node) {y,0};
}
sort(d+1,d+cnt+1);
f[0][0][0] = 1;
for(int i = 1; i <= cnt; i++) {
memset(f[i%2],0,sizeof(f[i%2]));
for(int j = 0; j <= n; j++) {
for(int k = 0; k <= j; k++) {
if(!f[(i-1)%2][j][k]) continue;
if(!d[i].type)
(f[i%2][j+1][k] += f[(i-1)%2][j][k]) %= mod;
else{
(f[i%2][j][j] += f[(i-1)%2][j][k]) %= mod;
if(j) (f[i%2][j-1][k] += f[(i-1)%2][j][k] * (j-k)) %= mod;
if(j&&k) (f[i%2][j-1][k-1] += f[(i-1)%2][j][k] * k) %= mod;
}
}
}
}
for(int j = 0;j <= n;j++)
(ans += f[0][j][0]) %= mod;
printf("%lld",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步