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. java语言基础-类型运算细节

    代码一: public class varDemo{ public static void main(String[] args) { byte a2; a2=3+4; System.out.prin ...

  2. qt 设置阴影 不显示黑色边框

    this->setAttribute(Qt::WA_TranslucentBackground);

  3. 洛谷 P2515 [HAOI2010]软件安装

    题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是 ...

  4. centos7 搭建双网卡bond1(主备模式)实例

    前景须知: 在redhat6 中网卡叫bond,在redhat7及centos7中改名team,此处只记录centos7中双网卡主备搭建过程. 应用情景:实现网络的高可用,防止一条网线或交换机故障影响 ...

  5. PHP03 移动互联网和PHP

    学习要点 移动互联网 云计算 网络通信协议 Apache http服务器 PHP运行原理 学习目标 理解网络通信协议 掌握PHP运行原理 WAMP开发环境的搭建   移动互联网 定义 移动互联网,就是 ...

  6. JavaEE-02 JSP数据交互01

    学习要点 request对象 response对象 转发与重定向 session对象 include指令 课程回顾 需求描述:编写JSP页面,计算2000—3000年中存在几个闰年. 实现分析:判断闰 ...

  7. hdu 6441 Find Integer(费马大定理+勾股数)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6441(本题来源于2018年中国大学生程序设计竞赛网络选拔赛) 题意:输入n和a,求满足等式a^n+b^ ...

  8. Sphinx排序模式

    目前SPHINX支持6种排序模式.分别是: 1. SPH_SORT_RELEVANCE2. SPH_SORT_ATTR_DESC3. SPH_SORT_ATTR_ASC4. SPH_SORT_TIME ...

  9. TCP三次握手简单理解

  10. c++_加法变乘法

    加法变乘法 我们都知道:1+2+3+ ... + 49 = 1225现在要求你把其中两个不相邻的加号变成乘号,使得结果为2015 比如:1+2+3+...+10*11+12+...+27*28+29+ ...