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. sql查询作业执行时间

    SELECT  j.name                        AS Job_Name        ,        h.step_id                     AS S ...

  2. SQLite-And和OR运算符

    SQLite - AND 和 OR 运算符 SQLite AND . OR运算符用于编译多个条件缩小在一个SQLite声明中选定的数据.这两个操作符被称为连接的操作符. 这些操作符与不同操作提供了一种 ...

  3. git 本地与远程仓库出现代码冲突解决方法

    提交过程中报错: [python@heaven-00 Selesystem]$ git push -u origin masterUsername for 'https://github.com': ...

  4. Open Cascade创建自己的MFC文档程序

    项目初始设置在Visual studio中创建一个单文档MFC项目(本例以MFCTest为名称): 在项目属性的VC++页面设置包含目录.库目录,在链接器的输入中添加OCC库目录下的所有.lib文件名 ...

  5. 写一个函数,求一个字符串的长度,在main函数中输入字符串,并输出其长度

    import java.util.Scanner; /** * [程序38] * * 题目:写一个函数,求一个字符串的长度,在main函数中输入字符串,并输出其长度. * * @author Jame ...

  6. No-6.用户权限相关命令

    用户权限相关命令 目标 用户 和 权限 的基本概念 用户管理 终端命令 组管理 终端命令 修改权限 终端命令 01. 用户 和 权限 的基本概念 1.1 基本概念 用户 是 Linux 系统工作中重要 ...

  7. 时间函数datetime time

    time模块 time翻译过来就是时间,有我们其实在之前编程的时候有用到过. #常用方法 1.time.sleep(secs) (线程)推迟指定的时间运行.单位为秒. 2.time.time() 获取 ...

  8. Django中的Cookie、Session、Token

    Cookie : 指望着为了辨别用户身份.进行会话跟踪而存储在用户本地的数据(通常经过加密),是由服务端生成,发送给客户端浏览器,浏览器会将Cookie以key/value保存,下一请求同一网站是就发 ...

  9. ssh服务使用介绍二

    老司机开车了 快上车 上文提到当我们使用ssh远程链接主机的时候,会出现询问的提示,如果我们链接的机器多了,一遍一遍的输入是不是很麻烦?怎么解决如下 vim /etc/ssh/ssh_config 如 ...

  10. 【JavaEE-面试总结】(未完,待续···)

    目录: 一.Java基础 二.JavaEE基础 三.JavaEE进阶 四.数据库 五.数据结构&算法 六.高级(服务器) 一.Java基础 1.1 面向对象(封装.继承.多态) 访问权限修饰符 ...