Leetcode 第 374 场双周赛 Problem D 100146. 统计感冒序列的数目(组合数学+阶乘+逆元)

  • Leetcode 第 374 场双周赛 Problem D 100146. 统计感冒序列的数目(组合数学+阶乘+逆元)
  • 题目
    • 给你一个整数 n 和一个下标从 0 开始的整数数组 sick ,数组按 升序 排序。
    • 有 n 位小朋友站成一排,按顺序编号为 0 到 n - 1 。数组 sick 包含一开始得了感冒的小朋友的位置。如果位置为 i 的小朋友得了感冒,他会传染给下标为 i - 1 或者 i + 1 的小朋友,前提 是被传染的小朋友存在且还没有得感冒。每一秒中, 至多一位 还没感冒的小朋友会被传染。
    • 经过有限的秒数后,队列中所有小朋友都会感冒。感冒序列 指的是 所有 一开始没有感冒的小朋友最后得感冒的顺序序列。请你返回所有感冒序列的数目。
    • 由于答案可能很大,请你将答案对 10 ^ 9 + 7 取余后返回。
    • 注意,感冒序列 不 包含一开始就得了感冒的小朋友的下标。
    • 2 <= n <= 10 ^ 5
    • 1 <= sick.length <= n - 1
    • 0 <= sick[i] <= n - 1
    • sick 按升序排列。
  • 示例
    • 示例 1:
    • 输入:n = 5, sick = [0,4]
    • 输出:4
      • 感冒序列 [1,2,3] ,被传染的顺序:[0,1,2,3,4] => [0,1,2,3,4] => [0,1,2,3,4] => [0,1,2,3,4]
      • 感冒序列 [1,3,2] ,被传染的顺序:[0,1,2,3,4] => [0,1,2,3,4] => [0,1,2,3,4] => [0,1,2,3,4]
      • 感冒序列 [3,1,2] ,被传染的顺序:[0,1,2,3,4] => [0,1,2,3,4] => [0,1,2,3,4] => [0,1,2,3,4]
      • 感冒序列 [3,2,1] ,被传染的顺序:[0,1,2,3,4] => [0,1,2,3,4] => [0,1,2,3,4] => [0,1,2,3,4]
    • 示例 2:
    • 输入:n = 4, sick = [1]
    • 输出:3
      • 感冒序列 [0,2,3] ,被传染的顺序:[0,1,2,3] => [0,1,2,3] => [0,1,2,3] => [0,1,2,3]
      • 感冒序列 [2,0,3] ,被传染的顺序:[0,1,2,3] => [0,1,2,3] => [0,1,2,3] => [0,1,2,3]
      • 感冒序列 [2,3,0] ,被传染的顺序:[0,1,2,3] => [0,1,2,3] => [0,1,2,3] => [0,1,2,3]
  • 解法
    • 组合数学+阶乘+逆元:
    • 第 1 步:
    • 分析题目易得每秒都 有且仅仅有一位未感冒者 被传染,且他的左或右一定有感冒的人,
    • 然后观察示例可以想到:未感冒者会组成 k 个连续区间,除了第一段以及看最后一段区间,中间区间全是左右均有感冒
    • 第 2 步:
    • 因为已感冒者无法被影响,因此先在区间内部考虑,再思考区间与区间的关系,
    • 第 3 步:
    • 区间内部的方案数:
      • 第一段或者最后一段仅有 1 种方案数,从右到左与从左到右
      • 中间区间 pre[i] 个人、方案数为:2 ^ (pre[i]-1)
        • 暴力枚举也可
        • DP 也行:dp[i] 代表 i 个人方案数由 i-1 个人方案数选 首/尾,且最后一个人无法选择:dp[i] = dp[i-1] * 2
    • 第 4 步
    • 每段区间方案数相乘即 总方案数:1 * 2 ^(per[1]-1 + … + per[k-1]-1)* 1
    • 但这仅是以整个区间来考虑的,如果形如:pre[0] 中选第一个、pre[2] 中选最后一个、pre[1] 中选第一个…
    • 我们将其称为排列数,
    • 第 5 步
    • 排序数:sum!/(per0!*per1!*…*perk!)
    • 设 pre[i] 总和为 sum,每个区间 per[i] 只有 1 种排序方式(从前到后顺序放入),而区间内部如何选由方案数决定,
    • 接着我们又两种思考方式(公式化简后可以互相转化)
      1. 先不管 per 顺序、仅看 sum 的总排序数为 sum!,每种 per 的总排序数 per! 变成 1 种排序方式,结果就是:sum!/ (per0! * per1! * … * perk!)
      2. 从 s 个空位中找到 per[0] 个位置顺序放入、结果为 C(s, per[0]),接着从 s-per[0] 个空位找 per[1] 个位置顺序放入、结果为 C(s-per[0], per[1]) … ,
    • 总结果就是 C(s, per[0])* C(s-per[0], per[1]) * … * C(s-per[0]-…-per[k-1], per[k])(可以化简为 sum!/ (per[0]! * per[1]! * … * per[k]!))
    • 第 6 步:
    • 结果就是:每种区间内部方案数 * 区间之间的排列数
  • 代码
/*** 组合数学+阶乘+逆元:** 第 1 步:* 分析题目易得每秒都 **有且仅仅有一位未感冒者** 被传染,且他的左或右一定有感冒的人,* 然后观察示例可以想到:未感冒者会组成 k 个连续区间,除了第一段以及看最后一段区间,中间区间全是左右均有感冒** 第 2 步:* 因为已感冒者无法被影响,因此先在区间内部考虑,再思考区间与区间的关系,** 第 3 步:* 区间内部的方案数:*     * 第一段或者最后一段仅有 1 种方案数,从右到左与从左到右*     * 中间区间 pre[i] 个人、方案数为:2 ^ (pre[i]-1)*         * 暴力枚举也可*         * DP 也行:dp[i] 代表 i 个人方案数由 i-1 个人方案数选 首/尾,且最后一个人无法选择:dp[i] = dp[i-1] * 2** **第 4 步**:* 每段区间方案数相乘即 **总方案数**:1 * 2 ^(per[1]-1 + ... + per[k-1]-1)* 1* 但这仅是以整个区间来考虑的,如果形如:pre[0] 中选第一个、pre[2] 中选最后一个、pre[1] 中选第一个...* 我们将其称为排列数,** **第 5 步**:* 排序数:sum!/(per0!*per1!*...*perk!)* 设 pre[i] 总和为 sum,每个区间 per[i] 只有 1 种排序方式(从前到后顺序放入),而区间内部如何选由方案数决定,* 接着我们又两种思考方式(公式化简后可以互相转化)*     1. 先不管 per 顺序、仅看 sum 的总排序数为 sum!,每种 per 的总排序数 per! 变成 1 种排序方式,结果就是:sum!/(per0!*per1!*...*perk!)*     2. 从 s 个空位中找到 per[0] 个位置顺序放入、结果为 C(s,per[0]),接着从 s-per[0] 个空位找 per[1] 个位置顺序放入、结果为 C(s-per[0],per[1]) ... ,*     总结果就是 C(s,per[0])*C(s-per[0],per[1])*...*C(s-per[0]-...-per[k-1],per[k])(可以化简为 sum!/(per[0]!*per[1]!*...*per[k]!))** 第 6 步:* 结果就是:每种区间内部方案数 * 区间之间的排列数**/public int numberOfSequence(int n, int[] sick) {long res = 1;// 排序数:sum!long perTotal = FAC[n - sick.length];// 排序数:per[0],代表第一个感冒左边多少个人int per = sick[0];perTotal *= INV_FAC[per];perTotal %= MOD;// 每段区间方案数相乘即 **总方案数**:1 * 2 ^(per[1]-1 + ... + per[k-1]-1)* 1int ansPow = 0;for (int i = 1; i < sick.length; i++) {// 排序数:sum!/(per0!*per1!*...*perk!)per = sick[i] - sick[i - 1] - 1;perTotal *= INV_FAC[per];perTotal %= MOD;// 中间的未感冒者有 2 ^ (per-1) 种方案数if (per > 0) {ansPow += per - 1;}}// 排序数:per[k],代表最后一个感冒右边多少个人per = n - sick[sick.length - 1] - 1;perTotal *= INV_FAC[per];perTotal %= MOD;// 每种区间内部方案数 * 区间之间的排列数res = qPow(2, ansPow, MOD) * perTotal % MOD;return (int)(res);}// 组合数模板private static final int MOD = (int)1e9+7;private static final int MX = 100_000;// 阶乘private static final long[] FAC = new long[MX];// 阶乘的逆元private static final long[] INV_FAC = new long[MX];static {FAC[0] = 1;for (int i = 1; i < MX; i++) {FAC[i] = FAC[i - 1] * i % MOD;}INV_FAC[MX - 1] = qPow(FAC[MX - 1], MOD - 2, MOD);for (int i = MX - 1; i > 0; i--) {INV_FAC[i - 1] = INV_FAC[i] * i % MOD;}}private static long qPow(long value, long pow, long mod) {long res = 1;while (pow > 0) {if ((pow & 1) == 1) {res *= value;res %= mod;}value *= value;value %= mod;pow >>= 1;}return res;}

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

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

相关文章

[RoFormer]论文实现:ROFORMER: ENHANCED TRANSFORMER WITH ROTARY POSITION EMBEDDING

文章目录 一、完整代码二、论文解读2.1 注意力机制2.2 绝对位置编码2.3 相对位置编码2.4 旋转位置编码Long-term decayAdaption for linear attention 2.5 模型效果 三、过程实现四、整体总结 论文&#xff1a;ROFORMER: ENHANCED TRANSFORMER WITH ROTARY POSITION EMBEDDING …

Java 使用itextpdf创建Pdf文件

DOM文件添加Maven依赖 <dependency><groupId>com.itextpdf</groupId><artifactId>itext7-core</artifactId><version>7.2.0</version><type>pom</type></dependency> 主要代码&#xff1a; PdfFont font PdfFo…

【数据结构】拆分详解 - 二叉树的链式存储结构

文章目录 一、前置说明二、二叉树的遍历  1. 前序、中序以及后序遍历   1.1 前序遍历   1.2 中序遍历   1.3 后序遍历 2. 层序遍历 三、常见接口实现  0. 递归中的分治思想  1. 查找与节点个数   1.1 节点个数   1.2 叶子节点个数   1.3 第k层节…

yo!这里是智能指针相关介绍

目录 前言 内存泄漏 RAII 智能指针原理 智能指针分类 auto_ptr unique_ptr shared_ptr 两个问题 线程安全 循环引用 后记 前言 对于智能指针&#xff0c;听起来很高大上&#xff0c;其实本质上就是一个类。为什么叫指针呢&#xff1f;因为可以像指针一样管理一块资…

linux 应用开发笔记---【I/O文件/基础篇 】

文章笔记来自于【速学Linux】手把手教你学嵌入式Linux C应用编程_哔哩哔哩_bilibili 一&#xff0c;什么是linux应用程序 1.运行在linux操作系统用户空间的程序 2.内核程序运行在内核空间&#xff0c;应用程序运行在用户空间 在终端执行的命令ls,ps。。。。。。都是运行在用…

使用gdb调试QEMU模拟的RISC-V平台程序

我们跑一个裸核程序&#xff0c;也就是不带操作系统的程序&#xff0c;然后使用gdb调试该程序。 首先编译目标程序&#xff0c;然后使用QEMU的kernel参数进行加载 qemu-system-riscv64 -s -S -bios opensbi.elf -m 4G -smp 4 -kernel my_program.x -nographic -s 让QEMU在12…

【MySQL的DQL查询语句】

MySQL的DQL查询语句-----在Navicat下 将学生表导入Navicat中查询语句查询一整张表查询年龄大于22年龄大于22的女生查找文科的学生查找六班的学生计算学生的总分 &#xff08;group by&#xff09;合并两表 &#xff08;join on xxxx&#xff09;合并两张表 并求总分先合并在聚合…

Java+springboot+avue医院绩效考核系统源码支持二次开发

公立医院改革要求建立公立医疗卫生机构绩效考核体系&#xff0c;借助绩效考核来引导各级公立医院把社会效益摆在首位&#xff0c;提高医疗服务质量&#xff0c;规范医疗服务行为&#xff0c;加强医院内部管理&#xff0c;促进医院高质量发展 医院绩效考核系统&#xff0c;建立以…

python 运用pandas 库处理excel 表格数据

文章目录 读取文件查看数据数据选择数据筛选创建新列计算并总结数据分组统计 读取文件 Pandas 是一个强大的数据分析库&#xff0c;它提供了丰富的数据结构和数据分析工具&#xff0c;其中之一是用于读取不同格式文件的 read_* 函数系列。以下是一个简单介绍如何使用 Pandas 读…

Siemens-NXUG二次开发-C/C++/Python环境配置[20231204]

Siemens-NXUG二次开发-C/C/Python运行方式[20231204] 1.NX/UG C/C/Python API官方开发文档2.运行方式2.1内部模式2.2 外部模式2.3 许可证书服务器启动 3.C/C环境配置4.Python环境配置5.第三方环境配置 1.NX/UG C/C/Python API官方开发文档 西门子NX/UG Python api开发文档&…

Spring学习笔记:Day2

昨天定的学习计划发现通过文心4.0来实现不靠谱&#xff0c;坑太多&#xff0c;今天开始跟随B站进行学习&#xff0c;争取10-15天学习一遍&#xff0c;冲啊&#xff01; 地址&#xff1a;001-课程介绍_哔哩哔哩_bilibili 今日规划&#xff1a; pt 001 - pt 018&#xff0c;提到…

【苍穹外卖】——第一天

第一天学习目标&#xff1a; 本系列只是对于学习苍穹外卖的一个学习总结和问题记录&#xff0c;学习的话还是照着黑马的视频学习 对内容有一个整体把握 搭建项目环境 对一些基础的名词理解 了解nginx反向代理和负载均衡 能使用Swagger测试后端接口 学习内容&#xff1a; pojo分…

小心处理 C++ 静态变量中的陷阱

小心处理 C 静态变量中的陷阱 函数中的 static 变量 static 变量的作用 C 中 static 关键字的最后一个用途是在函数内创建局部变量&#xff0c;这些变量在其作用域内退出和进入时保持其值。函数内的 static 变量类似于只能从该函数访问的全局变量。static 变量的一个常见用途…

【UGUI】实现背包的常用操作

1. 添加物品 首先&#xff0c;你需要一个包含物品信息的类&#xff0c;比如 InventoryItem&#xff1a; using UnityEngine;[CreateAssetMenu(fileName "NewInventoryItem", menuName "Inventory/Item")] public class InventoryItem : ScriptableObje…

网工学习7-配置 GVRP 协议

7.1GARP概述 GARP(Generic Attribute Registration Protocol)是通用属性注册协议的应用&#xff0c;提供 802.1Q 兼容的 VLAN 裁剪 VLAN pruning 功能和在 802.1Q 干线端口 trunk port 上建立动态 VLAN 的功能。 GARP 作为一个属性注册协议的载体&#xff0c;可以用来传播属性…

Java 原子操作类

一、原子类 1.1 基本原子类 AtomicBooleanAtomicIntegerAtomicLong 1.1.1 常用API public final int get() //获取当前的值public final int getAndSet(int newValue)//获取当前的值&#xff0c;并设置新的值public final int getAndIncrement()//获取当前的值&#xff0c;…

游泳馆会员服务预约管理系统预约小程序效果如何

游泳馆在各地每天都有大量用户前往&#xff0c;夏季室外、冬季室内也是学习游泳技术和休闲娱乐的好地方&#xff0c;而消费者大多是年轻人和家长带的孩子&#xff0c;这部分群体更显年轻化&#xff0c;因此在如今互联网环境下&#xff0c;传统商家需要进一步赋能客户消费路径。…

【Vue】Vue CLI 脚手架(Vue Command Line Interface)安装教程(通过npm)

前言 Vue CLI&#xff08;Vue Command Line Interface&#xff09;是一个基于Vue.js的官方脚手架工具&#xff0c;用于快速搭建和管理Vue.js项目。它提供了一套完整的开发工具和配置&#xff0c;包括项目初始化、开发服务器、热重载、构建和打包等功能。 Vue CLI使用了Webpac…

Doris 数据导出方式总结

1 Export导出 数据导出是Doris提供的一种将数据导出的功能。该功能可以将用户指定的表或分区的数据以文本的格式,通过Broker进程导出到远端存储上,如HDFS/BOS等。 1.1 基本原理 用户提交一个 Export 作业后。Doris 会统计这个作业涉及的所有 Tablet。然后对这些 Tablet 进行分…

自动驾驶学习笔记(十三)——感知基础

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《Apollo Beta宣讲和线下沙龙》免费报名—>传送门 文章目录 前言 传感器 测距原理 坐标系 标定 同…