3193: [JLOI2013]地形生成


Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 459  Solved: 223
[Submit][Status][Discuss]

Description


 
 
最近IK正在做关于地形建模的工作。其中一个工作阶段就是把一些山排列成一行。每座山都有各不相同的标号和高度。为了遵从一些设计上的要求,每座山都设置了一个关键数字,要求对于每座山,比它高且排列在它前面的其它山的数目必须少于它的关键数字。
 显然满足要求的排列会有很多个。对于每一个可能的排列,IK生成一个对应的标号序列和等高线序列。标号序列就是按顺序写下每座山的标号。等高线序列就是按顺序写下它们的高度。例如有两座山,这两座山的一个合法排列的第一座山的标号和高度为1和3,而第二座山的标号和高度分别为2和4,那么这个排列的标号序列就是1 2,而等高线序列就是3 4.
 现在问题就是,给出所有山的信息,IK希望知道一共有多少种不同的符合条件的标号序列和等高线序列。
 

Input


输入第一行给出山的个数N。接下来N行每行有两个整数,按照标号从1到N的顺序分别给出一座山的高度和关键数。
 

Output


 
输出两个用空格分隔开的数,第一个数是不同的标号序列的个数,第二个数是不同的等高线序列的个数。这两个答案都应该对2011取模,即输出两个答案除以2011取余数的结果
 

Sample Input



Sample Output


 

HINT


对于所有的数据,有1<=N<=1000,所有的数字都是不大于109的正整数。

分析:


先考虑第一个问题(先假设没有山高度相同):

我们把所有山按高度从大到小排序,设这个集合为S,设一个空集合为V。

我们把山按顺序放入集合V。

考虑第i座山放进去的时候能放的位置,因为现在前面有i - 1座山比它高,再加上本来的第i个位置,它一共有i个位置可以放。这个山的关键值如果为k,它只能在前min(k,i)个位置里挑。

所以第i个山的放的位置的组合为ci = min(k,i)种。ans = c1 * c2 …… * cn;

但是我们现在有山的高度相同,且关键值不同。两座高度相同的山能放的最靠后的位置,一定是关键值大的那个越靠后。所以我们先按高度从大到小,然后高度相同的关键值从小到大排序出S集合。

设[x,y]这段区间的山高度相同。所以 ci = min(x,k) + i - num。因为一座山在满足关键值的情况下,可以也放在高度相同的山前面。

所以最后 得出 ans1 = c1 * c2 …… * cn;

然后再看第二个问题,会产生重复情况的只有高度相同的山放一起的情况。

我们依然排序出V集合。按顺序插入山。

定义dp状态f[i][j],表示高度相同的山里面前i座,放在前j个位置的方案数。

因为我们是插入的山,比如说在一座高度为3的山后面再插入一座高度为3的山,此时是多了一种方案,是不会重复的。

状态也是很好转移设区间[x,y]山高度相同

f[i][j] = sum(f[i - 1][k] );k <= min(data[i].d,x) - 1;

因为是按顺序来刷表的可以省掉一维。

又因为f[i][j - 1] = sum(f[i][j - 1]);f[i][j] = sum(f[i - 1][k] );k <= min(data[i - 1].d,x) - 1;所以f[i][j] = f[i - 1][j] + f[i][j - 1]

最终方程dp[i] = dp[i - 1] + dp[i]

最后把每一区间[x,y]相同的山的ci = dp[0] + dp[1] +……dp[min(data[y].d,x) - 1]乘起来。

ans2 = c1 * c2 …… * cn;

就可以了。

AC代码:


# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
using namespace std;
const int mod = ;
const int N = ;
int dp[N],h[N],n,ans1 = ,ans2 = ;
struct Mountain{
int h;
int d;
bool operator <(const Mountain & other)const{
if(h == other.h)return d < other.d;
return h > other.h;
}
}data[N];
void Init(){
memset(dp,,sizeof dp);
dp[] = ;
}
void read(){
scanf("%d",&n);
for(int i = ;i <= n;i++){
scanf("%d %d",&data[i].h,&data[i].d);
}
sort(data + ,data + n + );
int num = ;
for(int i = ;i <= n;i++){
if(data[i].h != data[num].h)num = i;
(ans1 *= min(num,data[i].d) + i - num) %= mod;
}
printf("%d",ans1);
}
void work(){
int pos;
for(int i = ;i <= n;i++){
pos = i;
while(data[pos].h == data[i].h && pos <= n)pos++;
pos--;Init();
for(int j = i;j <= pos;j++){
for(int k = ;k <= min(data[j].d,i) - ;k++){
(dp[k] = dp[k - ] + dp[k]) %= mod;
}
}
int sum = ;
for(int j = ;j <= min(data[pos].d,i) - ;j++)(sum += dp[j]) %= mod;
(ans2 *= sum) %= mod;
i = pos;
}
printf(" %d\n",ans2);
}
int main()
{
read();
work(); }

[Bzoj3193][JLOI2013]地形生成 (排列组合 + DP)的更多相关文章

  1. [bzoj3193][JLOI2013]地形生成_排列组合_贪心

    [JLOI2013]地形生成 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3193 题解: 这种求总排列的题,一种常规做法就是所有的元素 ...

  2. BZOJ3193 [JLOI2013]地形生成 【dp】

    题目链接 BZOJ3193 题解 注意\(key\)是小于 第一问,显然按高度降序排序,逐个插入 如果高度各不相同,那么之前插入的都比当前插入的\(i\)大,可插入的位置个数就确定了 由于存在高度相同 ...

  3. BZOJ3193: [JLOI2013]地形生成

    传送门 Sol 第一问可以考虑按照山的高度从大到小放 但是这样如果遇到高度相同的就不好考虑,那么同时要求数量限制从小到大 这样每次放的时候后面的一定不会影响前面,并且高度相同的时候前面能放的位置后面的 ...

  4. BZOJ 3193: [JLOI2013]地形生成 计数 + 组合 + 动态规划

    第一问: 先不考虑山的高度有相同的:直接按照高度降序排序,试着将每一座山插入到前面山的缝隙中. 当然,这并不代表这些山的相对位置是固定的,因为后面高度更低的山是有机会插入进来的,所以就可以做到将所有情 ...

  5. 【BZOJ3193】 [JLOI2013]地形生成

    BZOJ3193 [JLOI2013]地形生成 Solution 第一问不是很简单吗? 直接计数就好了. 第二问思考无果看了看hyj神仙的代码,发现可以dp求解. 具体可以看代码(其实主要是我说不清楚 ...

  6. 【BZOJ3193】[JLOI2013]地形生成 DP

    [BZOJ3193][JLOI2013]地形生成 Description 最近IK正在做关于地形建模的工作.其中一个工作阶段就是把一些山排列成一行.每座山都有各不相同的标号和高度.为了遵从一些设计上的 ...

  7. 【BZOJ3193】[JLOI2013]地形生成(动态规划)

    [BZOJ3193][JLOI2013]地形生成(动态规划) 题面 BZOJ 洛谷 题解 第一问不难,首先按照山的高度从大往小排序,这样子只需要抉择前面有几座山就好了.然而有高度相同的山.其实也不麻烦 ...

  8. [JLOI2013]地形生成[组合计数]

    题意 \(n\) 元素各有一个高度 \(h\) 和关键数字 \(b\) .求有多少个下标序列和高度序列,满足对任意 \(i\),\(j< i\) 且 \(h_j < h_i\)的 \(j\ ...

  9. [JLOI2013]地形生成

    JLOI2013过了好长时间,才写第四题.. 第一问比较好想. 第二问我想到了n^3次方的做法,但是数据....于是没敢写,然后上网查了一下题解,居然是O(n^3)过的,数据这么弱... /* * P ...

随机推荐

  1. Oracle EXPDP and IMPDP

    一.特点 • 可通过 DBMS_DATAPUMP 调用 • 可提供以下工具: – expdp – impdp – 基于 Web 的界面 • 提供四种数据移动方法: – 数据文件复制 – 直接路径 – ...

  2. SQLite-删除查询

    SQLite -删除查询 SQLite DELETE查询用于从一个表删除现有记录.您可以使用WHERE子句删除查询删除选定行,否则所有记录将被删除. 语法: 删除查询的WHERE子句的基本语法如下: ...

  3. 深入了解JVM(Java虚拟机)

    虚拟机 JRE由Java API和JVM组成,JVM通过类加载器(Class Loader)加类Java应用,并通过Java API进行执行. 虚拟机(VM: Virtual Machine)是通过软 ...

  4. Linux关闭命令行正在执行的程序

    Ctrl + C 终止    是强制中断程序的执行,,进程已经终止. Ctrl + Z   是将任务中止(暂停的意思),但是此任务并没有结束,他仍然在进程中他只是维持挂起的状态,用户可以使用fg/bg ...

  5. C ++ _多线程笔记

    #include<iostream>#include <thread>//创建线程需要添加的头文件 using namespace std;/*thread join(阻塞:主 ...

  6. luogu P1462 通往奥格瑞玛的道路--spfa+二分答案

    P1462 通往奥格瑞玛的道路 题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡 ...

  7. poj3710 Christmas Game

    题目描述 题解: 树上删边. 对于奇数长度的环,可以看做一条边. 对于偶数长度的环,可以看做什么都没有. 没有特别好的解释…… 代码: #include<cstdio> #include& ...

  8. java读取配置文件的推荐方法getResource、getResourceAsStream

    在java开发中经常会读取配置文件,如果把文件路径写死,就太LOW了,也不符合编码规范. 在网上找了一些资料后,发现有两种方法:xxx.class.getResource("")  ...

  9. selenium 浏览器基础操作(Python)

    想要开始测试,首先要清楚测试什么浏览器.如何为浏览器安装驱动,前面已经聊过. 其次要清楚如何打开浏览器,这一点,在前面的代码中,也体现过,但是并未深究.下面就来聊一聊对浏览器操作的那些事儿. from ...

  10. OERR: ORA-1410 "invalid ROWID" Master Note / Troubleshooting, Diagnostic and Solution (文档ID 1410.1)

    OERR: ORA-1410 "invalid ROWID" Master Note / Troubleshooting, Diagnostic and Solution (文档I ...