首页 > 其他分享 >「解题报告」P9197 [JOI Open 2016] 摩天大楼

「解题报告」P9197 [JOI Open 2016] 摩天大楼

时间:2023-05-28 09:02:03浏览次数:47  
标签:P9197 int add MAXN 连续 JOI 2016 DP

水个题。

好像是连续段 DP 模板题,但是没怎么做过连续段 DP。

连续段 DP 大致思想就是对排列的计数,可以按照某个顺序依次填入每个数,将当前填的数看做若干连续段,每次考虑合并两个连续段,新建两个连续段或拓展一个连续段,然后就容易对排列进行计数了。

这题有一个绝对值的限制,而我们可以把绝对值按照值域拆开,考虑每一段值域上有多少个数跨过这一段,即可统计贡献。那么此时我们就只需要考虑当前的连续段数了。然后直接转移即可。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1005, P = 1000000007;
int f[2][MAXN][MAXN][2][2];
int n, l, a[MAXN];
void add(int &a, int b) {
    a += b;
    if (a >= P) a -= P;
}
int main() {
    scanf("%d%d", &n, &l);
    if (n == 1) {
        printf("1\n");
        return 0;
    }
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    sort(a + 1, a + 1 + n);
    for (int i = n; i >= 2; i--) {
        a[i] -= a[i - 1];
    }
    a[1] = 0;
    int o = 0;
    f[0][0][0][0][0] = 1;
    for (int i = 1; i <= n; i++) {
        memset(f[o ^ 1], 0, sizeof f[o ^ 1]);
        for (int j = 0; j <= n; j++) for (int k = 0; k <= l; k++) for (int x = 0; x <= 1; x++) for (int y = 0; y <= 1; y++) {
            if (f[o][j][k][x][y]) {
                if (k + (2 * j - x - y) * a[i] <= l) {
                    add(f[o ^ 1][j + 1][k + (2 * j - x - y) * a[i]][x][y], 1ll * f[o][j][k][x][y] * (j + 1 - x - y) % P);
                    if (!x) add(f[o ^ 1][j + 1][k + (2 * j - x - y) * a[i]][1][y], f[o][j][k][x][y]);
                    if (!y) add(f[o ^ 1][j + 1][k + (2 * j - x - y) * a[i]][x][1], f[o][j][k][x][y]);
                    if (j) {
                        add(f[o ^ 1][j][k + (2 * j - x - y) * a[i]][x][y], 1ll * f[o][j][k][x][y] * (2 * j - x - y) % P);
                        if (!x) add(f[o ^ 1][j][k + (2 * j - x - y) * a[i]][1][y], f[o][j][k][x][y]);
                        if (!y) add(f[o ^ 1][j][k + (2 * j - x - y) * a[i]][x][1], f[o][j][k][x][y]);
                    }
                    if (j >= 2) add(f[o ^ 1][j - 1][k + (2 * j - x - y) * a[i]][x][y], 1ll * f[o][j][k][x][y] * (j - 1) % P);
                }
            }
        }
        o ^= 1;
    }
    int ans = 0;
    for (int i = 0; i <= l; i++) {
        add(ans, f[o][1][i][1][1]);
    }
    printf("%d\n", ans);
    return 0;
}

标签:P9197,int,add,MAXN,连续,JOI,2016,DP
From: https://www.cnblogs.com/apjifengc/p/17437760.html

相关文章

  • wait,notify,notifyAll,sleep,join等线程方法的全方位演练
    一、概念解释1.进入阻塞:有时我们想让一个线程或多个线程暂时去休息一下,可以使用wait(),使线程进入到阻塞状态,等到后面用到它时,再使用notify()、notifyAll()唤醒它,线程被唤醒后,会等待CPU调度。不过需要注意的是:在执行wait()方法前必须先拿到这个对象的monitor锁。2.线程......
  • JOISC 2017 题解
    JOISC2017Day1开荒者Cultivation首先进行转化,转化为对于每个点\(x,y\),将其扩成一个左上角为\((x-a,y-c)\)右下角为\((x+b,y+d)\)的矩形后覆盖整个\(R\timesC\)的大举行。首先考虑枚举\(a,b\),那么我们可以得到平面上的几条垂直线段,那么我们可以得到一些关于\(c,d\)......
  • pwn1_sctf_2016
    先检查一下开了什么保护机制打开32位ida看看这个是啥鸭,像这种c++的代码最难看了,只能一个函数一个函数的百度我在这边简述一下,这些函数一大串就是实现了把s数组中的I整体替换成了you,其他的就没了,然后我们先去找找有没有后门函数之类的找到了一个叫做get_flag的函数,打开一看......
  • 「解题报告」P9195 [JOI Open 2016] JOIRIS
    发现上午高强度想题之后下午就啥都不想干了。神秘构造题,我属实是啥也不会了。先把下标改成从\(0\)开始。首先看到格子上的连续\(k\)的骨牌显然能想到将格子\(k\)染色。而由于有删除一行的操作,按照普通的染色方法好像并不好看,所以我们按列染色。这样我们统计每个颜色上的......
  • windows server2016 操作系统修改默认远程端口
    一、需求   远程端口,windows默认的3389.linux的22,这种都是知名端口,如果IP地址暴露,很可能会被攻击,这时候就需要更改端口号。二、操作步骤2.1打开注册表   快捷键WIN+R,命令行窗口输入regedit2.2进入以下路径  这里是默认端口,修改为自己除1024以后,以及未被......
  • JOISC 2021 题解
    JOISC21フードコート(FoodCourt)首先我们发现我们这个删除实际上可以假删除,我们每次问询时求出这个队列目前被删了几个(维护区间加,区间\(\max(0,A-x)\))就可以把删除操作给弄掉了。然后我们考虑对商店做扫描线!因为我们现在其实就是对商店的单点问询,我们这个加入操作也可以在左......
  • Elasticsearch 之 join 关联查询及使用场景
    在Elasticsearch这样的分布式系统中执行类似SQL的join连接是代价是比较大的,然而,Elasticsearch却给我们提供了基于水平扩展的两种连接形式。这句话摘自Elasticsearch官网,从“然而”来看,说明某些场景某些情况下我们还是可以使用的一、join总述1、关系类比在关系型数据库中,以MySQ......
  • Elasticsearch之join关联查询及使用场景 | 京东云技术团队
    在Elasticsearch这样的分布式系统中执行类似SQL的join连接是代价是比较大的,然而,Elasticsearch却给我们提供了基于水平扩展的两种连接形式。这句话摘自Elasticsearch官网,从“然而”来看,说明某些场景某些情况下我们还是可以使用的一、join总述1、关系类比在关系型数据库中,以MySQL为......
  • JOISC 2022 题解
    JOISC2022Day1监狱Jail首先我们发现操作一定是给所有人排序,然后按照顺序直接从\(s_i\)挪到\(t_i\),要求是对于\(i\),所有在它之前挪的\(t\)不能在\(s_i\tot_i\)上,所有在它之后挪的\(s\)不能在\(s_i\tot_i\)上。有了这个条件我们就可以\(O(n^2)\)建图。但是这样......
  • NOIP2016普及组试题题解
    1.买铅笔代码:#include<bits/stdc++.h>#definelllonglongusingnamespacestd;intn,ans=1e9,a,b;intmain(){ cin>>n; for(inti=1;i<=3;i++){ cin>>a>>b; ans=min(ans,int(ceil(n*1.0/a)*b)); } cout<<ans; return0;}......