P3643 [APIO2016] 划艇 分析

news/2025/10/19 4:41:06/文章来源:https://www.cnblogs.com/high-sky/p/19148931

题目概述

题目链接:https://www.luogu.com.cn/problem/P3643。

给你 \(n\) 个班级,每个班级要么不选数要么选的数在 \([a_i,b_i]\),且选的数比编号比他小的班级选的数都要大,问有多少种方案(对 \((10^9+7)\) 取模)。

分析

感觉挺经典的,而且这里的 trick 很通用,所以记录一下。

首先我们不难想到一个最最最暴力的 \(dp\)

\(f_{i,j}\) 表示前 \(i\) 个班级已经处理完毕,当前 \(i\) 必选且选择的数为 \(j\) 的方案数。

显然有:

\[f_{i,j}=\sum_{lst=0}^{i-1}\sum_{w=a_{lst}}^{b_{lst}}f_{lst,w} \]

那么我们一分也拿不了。

我们考虑怎么离散化让这个变得简单起来(这是重点)。

我们这个离散化主要是想要把一个区间离散化成一个更小的区间,可以想到区间覆盖的东东。

那么所以我们可以考虑这样一个 \([x,y)\) 区间离散化即可,为什么不用 \([x,y]\) 呢,会有一些边界问题,前者更好处理。

然后我们考虑怎么映射回来。

先重新定义 \(f\) 表示前 \(i\) 个班级处理完毕,当前 \(i\) 必选且选择的数落在区间 \(j\) 的方案数(这里的区间最多是 \(\mathcal{O}(n)\) 的)。

对于之前的班级选择的数不在 \(j\) 这个区间,也就是在之前,这是好转移的。

但是如果在这个区间呢?似乎有有点难办。

我们考虑有 \(m\) 个班级在这个区间,\(len\) 表示这个区间的长度,严格递增地选数,且可以不选的方案。

那么我们可以补 \(0\),然后从里面任意选 \(m\) 个,也就是 \(C_{m+len-1}^{m}\)

这个显然是对的。

于是我们的转移就有了:

\[f_{i,j}=\sum_{lst=0}^{i-1}\sum_wC_{m+len-1}^{m}f_{lst,w} \]

显然可以用前缀和优化。

代码

时间复杂度 \(\mathcal{O}(n^3)\),这个代码实现得十分精妙。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#define int long long
#define N 505
// #define M 1505
#define getid(x) (lower_bound(ls.begin(),ls.end(),x) - ls.begin())
using namespace std;
const int mod = 1e9 + 7;
int jc[N],inv[N];
// int C(int a,int b) {
//     if (a < 0 || b < 0 || a < b) return 0;
//     return jc[a] * inv[b] % mod * inv[a - b] % mod;
// }
int n,a[N],b[N],f[N],g[N];
signed main(){inv[0] = inv[1] = 1;for (int i = 2;i < N;i ++) inv[i] = (mod - mod / i) * inv[mod % i] % mod;vector<int> ls;cin >> n;for (int i = 1;i <= n;i ++) {scanf("%lld%lld",&a[i],&b[i]);b[i] ++;ls.push_back(a[i]),ls.push_back(b[i]);}stable_sort(ls.begin(),ls.end());ls.erase(unique(ls.begin(),ls.end()),ls.end());for (int i = 1;i <= n;i ++) a[i] = getid(a[i]),b[i] = getid(b[i]);f[0] = 1;for (int j = 0;j < (int)ls.size() - 1;j ++) {int len = ls[j + 1] - ls[j];g[0] = 1;for (int i = 1;i <= n;i ++) g[i] = g[i - 1] * (i + len - 1) % mod * inv[i] % mod;for (int i = n;i;i --)if (a[i] <= j && j < b[i]) {for (int c = 1,k = i - 1;k >= 0;k --) {f[i] = (f[i] + g[c] * f[k] % mod) % mod;if (a[k] <= j && j < b[k]) c ++;}}}int ans = 0;for (int i = 1;i <= n;i ++) ans = (ans + f[i]) % mod;cout << ans;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/939198.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

day016

今日完成:mysql的添加等基础操作 明日完成:mysql 遇到问题:无

uml九图和数据流图总结

UML九图与数据流图详解 在软件工程领域,系统建模是确保软件开发过程高效、准确的关键环节。UML(统一建模语言)和数据流图(DFD)作为两种重要的建模工具,在需求分析、系统设计和开发沟通中发挥着不可替代的作用。本…

UpdateSourceTrigger和Mode的区别

在WPF中: UpdateSourceTrigger= 只决定“什么时候”把值推回源; Mode= 决定“要不要”推回源。 默认 Mode=OneWay 时,绑定引擎根本不会注册“目标→源”的管道,你就算把 UpdateSourceTrigger 写成 PropertyChanged…

3DVG的当前面临的挑战和问题 - 教程

3DVG的当前面临的挑战和问题 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco…

NOIP2020 T2

给定长度为 \(n(1 \le n \le 2^{20})\) 的字符串 \(s\),问有多少种合法的拆分方式?一种合法的拆分方式:\(s = (AB)^iC(i > 0)\)其中 \(A,B,C\) 为非空字符串,\((AB)^i\) 为 \(i\) 个 \(AB\) 拼接的结果。 \(F(A…

Alex-VGG3

鉴于之前的两次对照实验都无法提现出AlexNet和VGG的区别,我调节了训练的样本数据,也对代码进行了调整,数据集从原先的CIFAR-10: 10类 换成了CIFAR-100: 100类 训练代码和结果如下 import torch import torch.nn as …

第二章日志分析-redis应急响应

第二章日志分析-redis应急响应 1、通过本地 PC SSH到服务器并且分析黑客攻击成功的 IP 为多少,将黑客 IP 作为 FLAG 提交; ssh去到/var/log下面这里题目提示我们是redis我们打开redis.log cat redis.log| less -N可以看…

第一章 应急响应- Linux入侵排查

第一章 应急响应- Linux入侵排查 1、web目录存在木马,请找到木马的密码提交 这里告诉我们web目录存在木马 我们来到/var/www/html下面看到有一个1.php 使用cat命令查看发现是一句话木马,木马密码就为POST传参的值fla…

浏览器多开的方法

浏览器多开脚本的核心原理是通过创建带有特定启动参数的浏览器快捷方式,实现多实例独立运行。其技术实现主要基于以下几个关键机制:•脚本为每个浏览器实例创建独立的用户数据目录(如C:\多开浏览器\1、2、3...) •…

10月17号

今天进行了复习。 和外语学习。

第一章日志分析-mysql应急响

第一章日志分析-mysql应急响 1、黑客第一次写入的shell flag{关键字符串}在/var/www/html/sh.php下面有个php文件,查看文件内容flag{ccfda79e-7aa1-4275-bc26-a6189eb9a20b}2、黑客反弹shell的ip flag{ip} 在/var/log…

操作系统应用构建(十二)RustDesk 用户服务器搭建——东方仙盟筑基期

操作系统应用构建(十二)RustDesk 用户服务器搭建——东方仙盟筑基期pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: &quo…

超好用的浏览器多开小工具!轻松管理多个账号,可以无限制使用其他插件

vx:llike620 给大家分享一个我最近在用的神器脚本,解决了我多年来的烦恼——浏览器多开问题! 这是什么工具? 简单说,就是一个小程序,能帮你一键创建多个“独立”的浏览器。每个浏览器都像新装的一样,互相不干扰!…

微服务组件-Eureka 科技详解

微服务组件-Eureka 科技详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco",…

python-IDLE定制界面大小

找到: C:\python37\Lib\idlelib\config-main.def 这个文件 修改这个值即可

新学期每日总结(第10天)

今日 相较昨日 复习递归

List.subList() 返回值为什么不能强转成 ArrayList

先说结论 很多人用 subList() 的时候,可能会想当然地认为它返回的是一个新的 ArrayList。但实际上,subList() 返回的是原 List 的一个视图(View),并不是一个独立的 ArrayList 对象。 // 这样会报 ClassCastException A…

奶奶都能看懂的 C++ —— 手把手指针

用通俗易懂的方式讲解指针和引用,通过生活化比喻帮助初学者理解内存地址、解引用等核心概念,适合零基础学习者轻松入门 C++ 指针。引用 在正式介绍指针之前,先来看看什么是引用。 int a = 10; int &ref1 = a;你…

10/17

今天没课

CSP-2024 T4

T4 题意 一共进行k轮比赛 每轮的第G场有一个标签,表示擂主是编号小的还是大的那个 擂主的获胜条件为能力值大于等于当前的轮数 求最后所有可能的胜者的编号之和 每场比赛人数必须为2的次幂,不足的可以补过来任意能力值…