[洛谷P3643] [APIO2016]划艇
洛谷题目链接:[APIO2016]划艇
题目描述
在首尔城中,汉江横贯东西。在汉江的北岸,从西向东星星点点地分布着 \(N\) 个划艇学校,编号依次为 \(1\) 到 \(N\)。每个学校都拥有若干艘划艇。同一所学校的所有划艇颜色相同,不同的学校的划艇颜色互不相同。颜色相同的划艇被认为是一样的。每个学校可以选择派出一些划艇参加节日的庆典,也可以选择不派出任何划艇参加。如果编号为 iii 的学校选择派出划艇参加庆典,那么,派出的划艇数量可以在 \(a_i\) 至 \(b_i\) 之间任意选择(\(a_i \leq b_i\))。
值得注意的是,编号为 \(i\) 的学校如果选择派出划艇参加庆典,那么它派出的划艇数量必须大于任意一所编号小于它的学校派出的划艇数量。
输入所有学校的 \(a_i,b_i\) 的值,求出参加庆典的划艇有多少种可能的情况,必须有至少一艘划艇参加庆典。两种情况不同当且仅当有参加庆典的某种颜色的划艇数量不同。
输入输出格式
输入格式:
第一行包括一个整数 \(N\),表示学校的数量。
接下来 \(N\) 行,每行包括两个正整数,用来描述一所学校。其中第 \(i\) 行包括的两个正整数分别表示 \(a_i,b_i\)(\(1 \leq a_i \leq b_i \leq 10^9\))。
输出格式:
输出一行,一个整数,表示所有可能的派出划艇的方案数除以 \(1,000,000,007\) 得到的余数。
输入输出样例
输入样例#1:
2
1 2
2 3
输出样例#1:
7
说明
【样例解释】
在只有一所学校派出划艇的情况下有 \(4\) 种方案,两所学校都派出划艇的情况下有 \(3\) 种方案,所以答案为 \(7\)。
【数据范围】
子任务 \(1\)(\(9\) 分):\(1 \leq N \leq 500\) 且对于所有的 \(1 \leq i \leq N\),保证 \(a_i=b_i\)。
子任务 \(2\)(\(22\) 分):\(1 \leq N \leq 500\) 且 \(\sum_{i=1}^N (b_i-a_i) \leq 10^6\)。
子任务 \(3\)(\(27\) 分):\(1 \leq N \leq 100\)。
子任务 \(4\)(\(42\) 分):\(1 \leq N \leq 500\)。
题解: 首先来考虑这样一个问题:如果有\(3\)个相同的区间,每个区间可以选数也可以不选,但是每个区间最多只能取出一个数,区间内的数属于\([1,len]\),要求取出其中的值严格递增,方案数有多少种?
我们可以考虑用加法原理枚举一下每种情况:
- 一个区间都不选:\(C_3^0*C_{len}^0=1\)
- 只有一个区间取数:\(C_3^1*C_{len}^1=3*len\)
- 有两个区间取数:\(C_3^2*C_{len}^2=3*\frac{len*(len-1)}{2}\)
- 三个区间都取数:\(C_3^3*C_{len}^3=1*\frac{len*(len-1)*(len-2)}{6}\)
加起来就是$$C_{3}^{0} \times C_{len}^{0} + C_{3}^{1} \times C_{len}^{1} + C_{3}^{2} \times C_{len}^{2} + C_{3}^{3} \times C_{len}{3}$$因为$C_n^m=C_n^{n-m}$,式子也可以表示成:$$C_{3}{3} \times C_{len}^{0} + C_{3}^{2} \times C_{len}^{1} + C_{3}^{1} \times C_{len}^{2} + C_{3}^{0} \times C_{len}^{3}$$
考虑一下这个式子的实际意义:将一个长度为\(len+3\)的区间劈成两半,两边总共选出\(3\)个数,也就相当于:$$C_{len+3}^3$$
我们把这个结论扩展一下:有\(n\)个相同的区间,区间内的数的范围是\([1,len]\),每个区间可以选择取或不取数,但是一个区间最多只能取一个数,方案数为$$C_{len+n}^n$$
好的,那么这个和我们的题目有什么关系呢?
首先我们将划艇的数量离散,用\(tmp_i\)记录排名为\(i\)的值,我们设区间\(i\)表示\([tmp_i,tmp_{i+1})\)那么某个学校派出的划艇的数量一定是包含在一个或多个区间内的.设\(f[i][j]\)表示当前处理到第\(i\)个学校,且第\(i\)个学校派出的划艇数量在\(j\)区间内的方案数.那么如果某个学校派出的划艇数量与第\(i\)个学校派出的划艇数量没有交集,那么就可以直接加上这部分的方案数:$$len_j \times \sum_{i' = 0}^{k - 1}\sum_{j' = 0}^{j - 1}f[i'][j']$$
然后我们需要考虑枚举在\([0,i-1]\)中与学校\(i\)的派出人数有交集的学校,将交集这一部分的贡献用组合的方法算出来.假设现在已经扫到了学校\(k(k\in[0,i-1])\),\(k\)与\(i\)有交集,且\(k\)学校必须派出划艇,那么根据上面推出的结论,这一部分的贡献为:$$\sum_{i' = 1}^{i - 1}C_{i - i' + len - 1}^{i - i' - 1} \times \sum_{k' = 1}^{i' - 1}\sum_{j' = 1}^{j - 1}f[k][j]$$
然后,我们会发现直接这样算是\(O(n^5)\)的,但是我们又会发现前面枚举\(f[i^{'}][j^{'}]\)可以直接前缀和,那么时间复杂度又降到了\(O(n^3)\).
再讲一下初始化的问题,因为\(f[0][j]\)可以转移到\(f[1][...]\),这些状态都是合法的,所以\(f[0][j]=1\).\(f[i][0]\)同理.
这里链一个讲的非常好的博客
#include<bits/stdc++.h>
using namespace std;
const int N = 1000+5;
const int mod = 1e9+7;
int n, f[N][N*2], ans = 0, a[N], b[N], size = 0, tmp[N*2], cnt = 0, L[N], R[N], inv[N];
int main(){
ios::sync_with_stdio(false);
cin >> n, inv[1] = 1;
for(int i = 2; i <= n; i++) inv[i] = 1ll*(mod-mod/i)*inv[mod%i]%mod;
for(int i = 1; i <= n; i++)
cin >> a[i] >> b[i], tmp[++cnt] = a[i], tmp[++cnt] = b[i]+1;
sort(tmp+1, tmp+cnt+1), size = unique(tmp+1, tmp+cnt+1)-tmp-1;
for(int i = 1; i <= n; i++){
L[i] = lower_bound(tmp+1, tmp+size+1, a[i])-tmp;
R[i] = lower_bound(tmp+1, tmp+size+1, b[i]+1)-tmp;
}
for(int i = 0; i < size; i++) f[0][i] = 1;
for(int i = 1; i <= n; i++){
f[i][0] = 1; //
for(int j = L[i]; j < R[i]; j++){
int len = tmp[j+1]-tmp[j], c = len-1, m = 1; //
f[i][j] = 1ll*f[i-1][j-1]*len%mod;
for(int k = i-1; k >= 1; k--){
if(L[k] > j || j >= R[k]) continue;
m++, c = 1ll*c*(len+m-2)%mod*inv[m]%mod; //
(f[i][j] += 1ll*f[k-1][j-1]*c%mod) %= mod;
}
}
for(int j = 1; j < size; j++)
f[i][j] = ((long long)f[i][j]+f[i-1][j]+f[i][j-1]-f[i-1][j-1]+mod)%mod;
}
cout << (f[n][size-1]-1+mod)%mod << endl;
return 0;
}
[洛谷P3643] [APIO2016]划艇的更多相关文章
- 洛谷 P3643 - [APIO2016]划艇(dp)
题面传送门 一道难度中等的 \(dp\)(虽然我没有想出来/kk). 首先一眼 \(dp_{i,j}\) 表示考虑到第 \(i\) 个学校,第 \(i\) 个学校派出了 \(j\) 个划艇的方案数,转 ...
- 洛谷P3643 [APIO2016]划艇(组合数学)
题面 传送门 题解 首先区间个数很少,我们考虑把所有区间离散化(这里要把所有的右端点变为\(B_i+1\)代表的开区间) 设\(f_{i,j}\)表示考虑到第\(i\)个学校且第\(i\)个学校必选, ...
- Solution -「APIO 2016」「洛谷 P3643」划艇
\(\mathcal{Description}\) Link & 双倍经验. 给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...
- P3643 [APIO2016]划艇
P3643 [APIO2016]划艇 题意 一个合法序列可表示为一个长度为 \(n\) 的序列,其中第 \(i\) 个数可以为 0 或 \([l_i,r_i]\) 中一个整数,且满足所有不为零的数组成 ...
- LOJ 2567: 洛谷 P3643: bzoj 4584: 「APIO2016」划艇
题目传送门:LOJ #2249. 题意简述: 有 \(n\) 个位置,第 \(i\) 个位置可以填在 \([a_i,b_i]\) (\(1\le a_i\le b_i\le 10^9\))之间的整数, ...
- [组合][DP]luogu P3643 [APIO2016]划艇
题面 https://www.luogu.com.cn/problem/P3643 对于一个序列,第i项可取的值在{0}∪[ai,bi]之间,求使序列非零部分单调递增的方案数 分析 设 $f[i][j ...
- 题解 P3643 [APIO2016]划艇
题解 一种思路很好想:\(f_{i,j}\) 表示前 \(i\) 所学校中,第 \(i\) 所学校参赛且派出 \(j\) 艘划艇的方案数.(转移就不列了.) 这种方式有一个致命点,就是 \(j\) 的 ...
- 洛谷P3642 [APIO2016]烟火表演
传送门 题解 fy大佬好强……我根本看不懂…… //minamoto #include<bits/stdc++.h> #define ll long long using namespac ...
- 洛谷1640 bzoj1854游戏 匈牙利就是又短又快
bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...
随机推荐
- PHP面试题一
http://www.viphper.com/?p=28 1.用PHP打印出前一天的时间格式是2006-5-10 22:21:21(2分) $a = date("Y-m-d H:i:s&qu ...
- 使用Fabric自动化你的任务
Fabric是一个Python库,可以通过SSH在多个host上批量执行任务.你可以编写任务脚本,然后通过Fabric在本地就可以使用SSH在大量远程服务器上自动运行.这些功能非常适合应用的自动化部署 ...
- HighCharts点击柱形或饼块等加URL或Click事件
我们在做图表的时候,有时候需要在单个数据上加链接或点击事件,是在plotOptions里的events里设置的: 如下代码: plotOptions: { pie: { cursor: 'pointe ...
- Promise 记录
- 软工网络15团队作业8——Beta阶段敏捷冲刺(Day4)
提供当天站立式会议照片一张 每个人的工作 1.讨论项目每个成员的昨天进展 赵铭: 在知晓云上建立数据表 吴慧婷:做了背单词界面并学习了词库界面的设计. 陈敏: 我的词库-全部词汇功能/新建词汇功能全部 ...
- 工作中常用到的Linux命令
ps: (ps的参数分成basic, list, output, thread, miscellaneous) (basic) -e / -A 显示所有进程 (output) -o 输出指定字段 ls ...
- git bash使用(markdown版)
前言 我是通过这个来学习的.个人愚笨,琢磨了半天,终于搞通了,醉了醉了,以前一直使用svn,用git确实有点水土不服.本文以如何使用git为主来展开,不涉及太多理论. git是分布式的版本管理.什么叫 ...
- 相见恨晚的 scala - 01 [ 基础 ]
简洁到不行,多一个分号都是不应该. 学习笔记: centOS 下安装 scala 和安装 jdk 一毛一样 . 1 . 不同于 Java 的变量声明 :( 但是和 js 很像 ) /** * Crea ...
- python 查看与更换工作目录
1. 进入python控制台 2. 查看工作路径,需要导入os包: import os 3. 查看工作路径的命令: os.getcwd() 4. 修改工作路径的命令: os.chdir("d ...
- 理解Restful api的意义
RESTful API 只是API的设计规范或者是一套设计理论. 单就URL和Method这两个点,你可以这样理解: URL 是用来唯一标示一个互联网资源的,而 Method 是用来标识当前请求对该资 ...