当前位置: 首页 > news >正文

组合计数 + 拓扑序计数问题

目录

题目描述

问题分析

一、核心规则

二、关键结论

三、解题思路

拓展:逆元是什么?


题目描述


问题分析

一、核心规则

  1. 操作只有两种:INSERT idDELETE id
  2. 合法执行顺序的要求:
    • INSERT id必须在DELETE id之前执行(因为插入后才能删除)。
    • 初始执行顺序是合法的,且同一id只会出现一次INSERT和一次DELETE(或者只出现INSERT)。
    • 调整顺序后,最终数据库状态要和原顺序执行后的结果一致:
    • 最终状态里,存在的id是那些只执行了INSERT、没有执行DELETE的记录。
    • 被删除的id必须执行过INSERTDELETE,且INSERT在前。

二、关键结论

  • 对于每个id
    • 如果它有INSERTDELETE:这两条操作必须满足INSERTDELETE之前,是一个固定的先后约束。
    • 如果它只有INSERT:这条操作没有后续约束,只要不违反其他id的约束即可。
    • 如果它只有DELETE:题目保证原顺序合法,这种情况不存在(因为DELETE时必须存在该id,说明前面一定有INSERT)。
  • 所有合法顺序,就是满足所有INSERT(id) → DELETE(id)约束的拓扑序数量。

三、解题思路

  1. 预处理操作

    • 记录每个idINSERTDELETE操作是否存在。
    • 把所有操作分为两类:
      • 成对操作:(INSERT, DELETE),共k对。
      • 单条操作:仅INSERT,共m条。
    • 总操作数n = 2*k + m
  2. 计数公式推导

    • 我们先把n个操作全排列,有n!种方式。
    • 对于每一对(INSERT, DELETE),其中INSERTDELETE前的情况,只占所有排列的一半(每对的两种顺序中只有一种合法)。
    • 因此,总合法顺序数为: \(\text{ans} = \frac{n!}{2^k}\) 其中kINSERTDELETE成对的数量。
  3. 实现要点

    • 因为结果可能很大,通常题目会要求对1e9+7取模,我们用预处理阶乘 + 快速幂求逆元来计算。
    • 2^k的逆元可以用pow(2, k, MOD)的逆元计算。

Java 代码实现

import java.util.*; public class Main { static final int MOD = 1000000007; static final int MAX = 200010; // 假设 N 最大为 2e5 static long[] fact = new long[MAX]; // 快速幂 static long qpow(long a, long b) { long res = 1; while (b > 0) { if ((b & 1) == 1) { res = res * a % MOD; } a = a * a % MOD; b >>= 1; } return res; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); sc.nextLine(); // 预处理阶乘,fact[i] 存储 i! % MOD,方便后续直接取用 fact[0] = 1; for (int i = 1; i <= N; i++) { fact[i] = fact[i - 1] * i % MOD; } Map<Integer, Boolean> hasInsert = new HashMap<>(); Map<Integer, Boolean> hasDelete = new HashMap<>(); for (int i = 0; i < N; i++) { String line = sc.nextLine(); String[] parts = line.split(" "); if (parts[0].equals("INSERT")) { int id = Integer.parseInt(parts[1]); hasInsert.put(id, true); } else if (parts[0].equals("DELETE")) { int id = Integer.parseInt(parts[1]); hasDelete.put(id, true); } } // 统计成对的数量 k:遍历所有 INSERT 的 id,如果该 id 同时有 DELETE,则 k++ int k = 0; for (int id : hasInsert.keySet()) { if (hasDelete.containsKey(id)) { k++; } } // 计算 n! / (2^k) mod MOD long numerator = fact[N]; long denominator = qpow(2, k); long invDenominator = qpow(denominator, MOD - 2); // 费马小定理求逆元 long ans = numerator * invDenominator % MOD; System.out.println(ans); } }

拓展:逆元是什么?

逆元就是在模运算里把除法变成乘法,从而避免除法带来的问题(比如溢出、无法整除)

在模运算里,我们没法直接做除法。 比如:

  • 正常数学里,a ÷ b = a × (1/b)
  • 但在模运算里,1/b这个分数不存在,我们需要找一个整数inv(b),让它满足:
  • 这个inv(b),就叫做b在模MOD下的乘法逆元

有了逆元,除法就可以转换成乘法:

逆元怎么求?(费马小定理)

MOD是一个质数(比如题目里的1e9+7),且b(要除的那个数) 和MOD互质时,我们可以用费马小定理快速求逆元:

总结

  • 逆元的本质:模运算里的 “倒数”,让除法变成乘法。
  • 核心作用
    1. 解决模运算中无法直接做除法的问题
    2. 避免大数除法导致的溢出和计算错误
  • 使用前提:模数MOD是质数,且除数bMOD互质(题目里的21e9+7就满足)。
http://www.gsyq.cn/news/1439728.html

相关文章:

  • 护发精油功效对比测评:抚平毛躁哪家强? - 资讯快报
  • 260亿美元估值!Cognition AI融资背后,AI编程赛道机遇与挑战并存
  • 百度网盘下载加速终极指南:3种方法突破限速实现高速下载
  • 2026 乐清黄金回收|铂金钻石 K 金名表名包回收靠谱商家推荐 - 同城好物推荐官
  • 告别Docker Hub抽风:手把手教你用SSH给群晖NAS安装ddns-go动态域名
  • Dictionary的底层原理
  • 极限运动场施工为什么不能只看效果图? - 长华体育
  • 2026年5月邯郸靠谱黄金回收门店实测盘点:余生黄金回收984元/克领跑,全城6家口碑排行 - 余生黄金回收
  • 基于机器学习的智能电表用电异常检测与负荷预测系统实战
  • 吕梁 cppm 培训机构中供国培首选 - 中供国培
  • 2026.5.30 zsh题单
  • 智慧树学习助手:用自动化技术提升在线学习效率
  • 闲管家邀请码折扣码是什么 闲管家智能回复 - 李先生sir
  • Voclosporin伏环孢素作为钙调神经磷酸酶抑制剂治疗活动性狼疮肾炎的蛋白尿降低
  • 余生黄金回收综合实力登顶!2026年5月兰州黄金回收深度解析与服务阶梯指南 - 余生黄金回收
  • 从BibTeX到完美排版:我的Mendeley/Zotero自定义CSL格式踩坑全记录
  • EP0 Oh my zsh 快速安装
  • 2026年4月空心轴生产厂家有哪些,调质轴/镀铬光轴/直线光轴/空心轴/软轴/实心光轴/空心光轴,空心轴批发厂家推荐 - 品牌推荐师
  • 丽水足不出户黄金回收,六家机构上门服务避坑指南 - 上门黄金回收
  • 呼和浩特 cppm 培训机构中供国培首选 - 中供国培
  • 小白配置Vscode Claude Code 插件免费使用deepseek-v4-pro模型
  • 护发精油品牌对比:4个国货品牌VS进口品牌 - 资讯快报
  • AI Agent时代来临:智能体正在重塑互联网的下一阶段
  • 一次thinkbook蓝牙修复过程
  • AMD Ryzen + VMware装macOS避坑大全:从镜像下载失败到VMware Tools安装报错的完整解决方案
  • 用STC89C51单片机+HC-SR04超声波模块,手把手教你做一个防误触的智能垃圾桶(附完整代码)
  • LLM 推理框架大战 2026:谁才是真正的性能王者?
  • 别死磕 `brctl` 了!一文讲透 Linux 网桥的“前世今生”与避坑指南(本文ai作为编辑)
  • 2026年|论文求生:AIGC检测走红,全网最全国内外10大免费降AI率工具避坑指南 - 降AI实验室
  • 【SRC漏洞挖掘系列】第15期:自动化与AI赋能 —— 打造你的专属“漏洞挖掘机”