• 2020.7.4模拟 数据结构 (ds)


    题目描述

    (wobmaj)(N)个数据结构,第(i)个数据结构具有工业指数(A_i)和包容指数(B_i(B_ile A_i))
    他会不断执行下面这个操作,直到无法再执行为止:
    选择二元组((i,j)),将第(i)个数据结构套进第(j)个数据结构里,其中(A_i<B_j)
    每个数据结构只能嵌套和被嵌套一次。
    求可能出现的不同局面的数量。答案对(10^9+7)取模。
    (Nle 300,B_i<A_i<10^9)

    数据范围很小,(DP)可行。
    因为(B_ile A_i),所以一个数据结构不能嵌套自己。
    因为要执行到无法再执行为止,所以嵌套的数据结构数是固定并且最大的。
    将一个数据结构拆成(A_i,B_i)两个点,从大到小排序,保证枚举到的(A_i)能被前面枚举的(B_i)嵌套。因为(A_i=B_j)时不能嵌套,所以相等时(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)点,则可以分三种情况讨论:
      • 不嵌套:
        如果(A_i)不被嵌套,那么(A_i)之前的所有(B)点必须在后面嵌套,否则,一定可以把(A_i)和前面的某一个(B)点嵌套,使得嵌套数量(+1),说明当前的嵌套数没有达到最大。
        (f[i][j][k])表示在(j)个可选的(B)点中,有(k)个是必选((kle 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 ]

    统计答案时,如果有必选点剩余则不合法。
    最后答案即为(sum limits_{j=1} ^{n} f[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;
    }
    
  • 相关阅读:
    编程 判断 是否满足条件 的 验证代码。
    Javascript作用域详解。
    DateTable To Json
    反射_获取字段的Description信息
    C# Json格式
    jQuery选择器
    SQL日期格式转换
    【转载】#pragma once与#ifndef
    C++中的左值与右值
    HTML、CSS基础知识
  • 原文地址:https://www.cnblogs.com/mogeko/p/13236121.html
Copyright © 2020-2023  润新知