盘锦市网站建设_网站建设公司_测试上线_seo优化
2026/1/2 18:29:20 网站建设 项目流程

P4588 [TJOI2018] 数学计算

题目描述

小豆现在有一个数 \(x\),初始值为 \(1\)。小豆有 \(Q\) 次操作,操作有两种类型:

1 m:将 \(x\) 变为 \(x \times m\),并输出 \(x \bmod M\)

2 pos:将 \(x\) 变为 \(x\) 除以第 \(pos\) 次操作所乘的数(保证第 \(pos\) 次操作一定为类型 1,对于每一个类型 1 的操作至多会被除一次),并输出 \(x \bmod M\)

输入格式

一共有 \(t\) 组输入。

对于每一组输入,第一行是两个数字 \(Q,M\)

接下来 \(Q\) 行,每一行为操作类型 \(op\),操作编号或所乘的数字 \(m\)(保证所有的输入都是合法的)。

输出格式

对于每一个操作,输出一行,包含操作执行后的 \(x \bmod M\) 的值。

输入输出样例 #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\%\) 的数据,\(1 \le Q \le 500\)

对于 \(100\%\) 的数据,\(1 \le Q \le 10^5\)\(t \le 5,1 \lt M \le 10^9\)\(0 < m \leq 10^9\)

题解

第一反应是直接模拟,直接把每次操作的数计算下来就好,然后操作二的时候直接除就好
然后发现你要除去的是真实的\(x\times m\),你输出的是 \(x\times m \mod M\) ,如果只是单纯的记录 \(x\times m\) ,毫无疑问会爆 long long
当然我们可以直接上python,但是感觉出题人一样会把我们卡死
那使用乘法逆元直接去做似乎可以,然后发现 \(M\) 是输入的,没有保证一定是质数,也没有保证 \(x\mod M \neq 0\) ,乘法逆元也被出题人防死了

发现把每次操作看做一个位置,整个操作1的序列就是一个区间,当前操作就是要你维护类似整个区间的前缀积,然后我们就想到可以用类似线段树的方法维护
其实我开始根本看不出这和线段树有半根毛的关系

对于操作1 m, 将当前最尾部的操作位置的值设置为\(m\),然后线段树上更新前缀积
对于操作2 pos,将操作序列第pos 位置的值改成1(这和除法操作等价),然后线段树上更新维护前缀积
这样子我们通过维护前缀积,避免了记录除法/乘法逆元的操作,这样在取模意义下也是合法的

代码

#include<bits/stdc++.h> 
// #define mod 998244353
// #define int long long   //由于作者比较懒,所以直接使用这个了
using namespace std;
typedef long long ll;
typedef __int128 ix;
typedef long double ldb;
const ll V = 2e5 + 100;
const int INF = 1e9 + 7;
void solve() 
{int q,mod;cin >> q >> mod;vector<ll> mul(4 * q + 1);auto update = [&](int x) ->void{mul[x] = mul[2 * x] * mul[2 * x + 1] % mod;};auto build = [&](auto&& self,int now,int l,int r) ->void{if(l == r){mul[now] = 1;return ;}int mid = (l + r) >> 1;self(self,2 * now,l,mid);self(self,2 * now + 1,mid + 1,r);update(now);};auto modify = [&](auto&&self,int now,int l,int r,int x,int y,ll val) ->void{if(x <= l && r <= y){mul[now] = val % mod;return ;}int mid = (l + r) >> 1;if(x <= mid) self(self,2 * now,l,mid,x,y,val);if(mid + 1 <= y) self(self,2 * now + 1,mid + 1,r,x,y,val);update(now);};build(build,1,1,q);for(int i = 1;i <= q;++i){int opt,m;cin >> opt >> m;if(opt == 1) modify(modify,1,1,q,i,i,(ll)m);else modify(modify,1,1,q,m,m,1ll);ll ans = mul[1] % mod;cout << ans << "\n";}
}
signed main()
{std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout.tie(nullptr);int t;cin >> t;while(t--) solve();return 0;
}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询