\(\mathcal{Description}\)

  Link & 双倍经验.

  给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\{c_n\}\) 的个数,使得:

  • \(\forall i~~~~c_i=0\lor c_i\in[a_i,b_i)\)。
  • \(\forall i<j~~~~c_i\not=0\land c_j\not=0\Rightarrow c_i<c_j\)。

  对 \(10^9+7\) 取模。

  \(n\le500\),\(1\le a_i\le b_i\le10^9\)。

\(\mathcal{Solution}\)

  一个很 naive 的 DP 想法,\(f(i,j)\) 表示考虑前 \(i\) 个位置,\(c_i=j~(j\not=0)\) 时的方案数。问题在于第二维开销过大,考虑离散化所有端点坐标。

  先来一个引理,取值在 \([a,b)\),长度为 \(n\) 的上升整数序列的个数为 \(\binom{b-a}{n}\),显然选 \(n\) 个数就可以了。

  再来一个引理,取值在 \([a,b)\cup\{0\}\),长度为 \(n\),非零的位置是上升整数序列的序列个数为 \(\binom{b-a+n}{n}\),证明也很显然,有几个 \(0\) 可以选,虽然不同的 \(0\) 可以任意排列,但看上去都是一样的。所以钦定 \(0\) 的大小关系后就等价于令区间为 \([a-n,b]\),长度为 \(n\) 时的上一引理。

  接着刚才的思路,离散化时,排过序的端点们把坐标轴分为若左闭右开的区间,从左开始第 \(t\) 个区间称作第 \(t\) 段。令 \(f(i,j)\) 表示考虑前 \(i\) 个位置,\(c_i\) 属于前 \(j\) 段时的方案数。设 \([j,j+1)\) 实际映射 \([a,b)\),枚举 \(k<i\),转移:

\[f(i,j)\leftarrow f(i,j)+f(k,j-1)\binom{b-a+x-1}{x},~~~~\text{where }x=1+\sum_{t=k+1}^{j-1}[j\in[a_t,b_t)]
\]

  组合数运用了引理二。注意钦定 \(c_i\) 不为 \(0\),所以上面 \(-1\)。

  扫 \(f\) 就结束了,交换枚举顺序,第二维还可以滚掉。复杂度 \(\mathcal O(n^3)\)。

\(\mathcal{Code}\)

/* Clearink */

#include <cstdio>
#include <algorithm> const int MAXN = 500, MOD = 1e9 + 7;
int n, a[MAXN + 5], b[MAXN + 5], tmp[MAXN * 2 + 5], inv[MAXN + 5];
int f[MAXN + 5], comb[MAXN + 5]; inline int mul ( long long a, const int b ) { return a * b % MOD; }
inline int& addeq ( int& a, const int b ) { return ( a += b ) < MOD ? a : a -= MOD; } int main () {
scanf ( "%d", &n ), inv[1] = 1;
for ( int i = 1; i <= n; ++ i ) {
if ( i > 1 ) inv[i] = mul ( MOD - MOD / i, inv[MOD % i] );
scanf ( "%d %d", &a[i], &b[i] ), ++ b[i];
tmp[2 * i - 1] = a[i], tmp[i << 1] = b[i];
}
std::sort ( tmp + 1, tmp + ( n << 1 | 1 ) );
int m = std::unique ( tmp + 1, tmp + ( n << 1 | 1 ) ) - tmp - 1;
for ( int i = 1; i <= n; ++ i ) {
a[i] = std::lower_bound ( tmp + 1, tmp + m + 1, a[i] ) - tmp;
b[i] = std::lower_bound ( tmp + 1, tmp + m + 1, b[i] ) - tmp;
}
f[0] = 1;
for ( int j = 1, len; j < m; ++ j ) {
len = tmp[j + 1] - tmp[j], comb[0] = 1;
for ( int i = 1; i <= n; ++ i ) {
comb[i] = mul ( mul ( comb[i - 1], len + i - 1 ), inv[i] );
}
for ( int i = n; i; -- i ) {
if ( j < a[i] || b[i] <= j ) continue;
for ( int k = i - 1, c = 1; ~k; -- k ) {
addeq ( f[i], mul ( comb[c], f[k] ) );
if ( a[k] <= j && j < b[k] ) ++ c;
}
}
}
int ans = 0;
for ( int i = 1; i <= n; ++ i ) addeq ( ans, f[i] );
printf ( "%d\n", ans );
return 0;
}

\(\mathcal{Details}\)

  目前洛谷最优解,兔的代码吸口氧真的快到飞起 www。

Solution -「APIO 2016」「洛谷 P3643」划艇的更多相关文章

  1. [洛谷P3643] [APIO2016]划艇

    洛谷题目链接:[APIO2016]划艇 题目描述 在首尔城中,汉江横贯东西.在汉江的北岸,从西向东星星点点地分布着 \(N\) 个划艇学校,编号依次为 \(1\) 到 \(N\).每个学校都拥有若干艘 ...

  2. 洛谷P3643 [APIO2016]划艇(组合数学)

    题面 传送门 题解 首先区间个数很少,我们考虑把所有区间离散化(这里要把所有的右端点变为\(B_i+1\)代表的开区间) 设\(f_{i,j}\)表示考虑到第\(i\)个学校且第\(i\)个学校必选, ...

  3. 洛谷 P3643 - [APIO2016]划艇(dp)

    题面传送门 一道难度中等的 \(dp\)(虽然我没有想出来/kk). 首先一眼 \(dp_{i,j}\) 表示考虑到第 \(i\) 个学校,第 \(i\) 个学校派出了 \(j\) 个划艇的方案数,转 ...

  4. 「区间DP」「洛谷P1043」数字游戏

    「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...

  5. Solution -「JSOI 2019」「洛谷 P5334」节日庆典

    \(\mathscr{Description}\)   Link.   给定字符串 \(S\),求 \(S\) 的每个前缀的最小表示法起始下标(若有多个,取最小的).   \(|S|\le3\time ...

  6. Solution -「洛谷 P4372」Out of Sorts P

    \(\mathcal{Description}\)   OurOJ & 洛谷 P4372(几乎一致)   设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...

  7. Solution -「POI 2010」「洛谷 P3511」MOS-Bridges

    \(\mathcal{Description}\)   Link.(洛谷上这翻译真的一言难尽呐.   给定一个 \(n\) 个点 \(m\) 条边的无向图,一条边 \((u,v,a,b)\) 表示从 ...

  8. 「洛谷4197」「BZOJ3545」peak【线段树合并】

    题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...

  9. 「洛谷3338」「ZJOI2014」力【FFT】

    题目链接 [BZOJ] [洛谷] 题解 首先我们需要对这个式子进行化简,否则对着这么大一坨东西只能暴力... \[F_i=\sum_{j<i} \frac{q_iq_j}{(i-j)^2}-\s ...

随机推荐

  1. 【Warrior刷题笔记】剑指offer 32. 三道题,让你学会二叉树的深度广度优先遍历与递归迭代技术

    题目一 剑指 Offer 32 - I. 从上到下打印二叉树 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/cong-shang-dao-xi ...

  2. IE8和IE9下textarea滚动选中的问题

    在IE8和IE9下如果textarea设置了样式overflow-y:auto;就不可以滚动选中了,应该样式写成overflow:auto;有了纵向滚动实际上就不会出现横向滚动的情况,也没有必要ove ...

  3. 园子的推广博文:欢迎收看 Apache Flink 技术峰会 FFA 2021 的视频回放

    园子专属收看链接:https://developer.aliyun.com/special/ffa2021/live#?utm_content=g_1000316459 Flink Forward 是 ...

  4. RDA5807M开发指南 & 开源库函数

    文档标识符:RDA5807M_T-D-P16 作者:DLHC 最后修改日期:2022.1.14 最后修改内容:修改.添加内容 发布状态:已发布 本文链接:https://www.cnblogs.com ...

  5. 【C++】STL算法

    STL算法 标签:c++ 目录 STL算法 一.不变序列算法 1.熟悉的min(), max() 2.找最值还自己动手么?不了不了 3.熟悉的find()和新学会的count() 二.变值算法 1.f ...

  6. 【数学】立个flag

    想写一个叫做<机器学习中的数学基础>系列文章

  7. 【get√】golang新手理解了一点点gin框架的中间件

    1.通过use()来使用多个中间件 router := gin.New() router.Use( middleware1, middleware2) 2.中间件的典型实现 func Logger() ...

  8. SNAT技术

    前面在讲解 firewall-config 工具的功能时,曾经提到了 SNAT(Source Network Address Translation,源网络地址转换)技术.SNAT 是一种为了解决 I ...

  9. 微信小程序笔记整理--入门篇。

    7-2 微信小程序入门篇 准备篇 1.登录网址,https://mp.weixin.qq.com 注册一个微信小程序. 2.获取微信小程序appid,登录自己的小程序后台,在开发者设置中获得appid ...

  10. 初步认识微前端(single-spa 和 qiankun)

    初步认识微前端 微前端是什么 现在的前端应用,功能.交互日益复杂,若只由一个团队负责,随着时间的推进,会越来越庞大,愈发难以维护. 微前端这个名词,第一次提出是在2016年底.它将微服务(将单一应用程 ...