当前位置:网站首页>Luogu P4588: [TJOI2018]数学计算
Luogu P4588: [TJOI2018]数学计算
2022-08-05 08:11:00 【9ack!?】
题目大意
题目大意是这样对于一个数字x,有若干种操作:
- 操作1是对x乘上一个数字m
- 操作2是让x第pos次的操作失效
每次操作后输出当前x对一个数字取模的值。这个问题乍一看挺简单,但是由于取模的数字不一定是质数,所以逆元也不能用了,暴力做法不行我们就思考一些巧妙的方法。通过时间当作下标来把这些m组织起来,再用线段树维护所有段的乘积,操作1就是把当前时间对应的值置为m,操作2就是把当前时间对应的值置为1。
由于每次都需要精确递归到长度为1的段,所以标记也不需要打,直接开干。
代码
#include <cstdio>
#include <algorithm>
using namespace std;
#define lc k<<1
#define rc k<<1|1
typedef long long ll;
const int maxn = 1e5+5;
ll a[maxn], f[maxn*4];
int q, M;
void build(int k, int l, int r) {
f[k] = 1;
if(l == r) return;
int m = (l+r) >> 1;
build(lc, l, m);
build(rc, m+1, r);
}
inline void mul(int k, int l, int r, int t, int p) {
if(l == r) {
f[k] = p; return; }
int m = (l+r) >> 1;
if(t <= m) {
mul(lc, l, m, t, p);
} else
mul(rc, m+1, r, t, p);
f[k] = (f[lc]*f[rc])%M;
}
inline void div(int k, int l, int r, int t) {
if(l == r) {
f[k] = 1; return; }
int m = (l+r) >> 1;
if(t <= m) {
div(lc, l, m, t);
} else
div(rc, m+1, r, t);
f[k] = (f[lc]*f[rc])%M;
}
int main(void)
{
freopen("in.txt", "r", stdin);
int t;
scanf("%d", &t);
while(t--) {
scanf("%d%d", &q, &M);
build(1, 1, q);
int op, p;
for(int i = 1; i <= q; ++i) {
scanf("%d%d", &op, &p);
if(op == 1) {
mul(1, 1, q, i, p);
} else {
div(1, 1, q, p);
}
printf("%lld\n", f[1]%M);
}
}
return 0;
}
边栏推荐
猜你喜欢
随机推荐
青苹果论坛重新开放
Pagoda measurement - building small and medium-sized homestay hotel management source code
手机上流行的各类谜语
Use of thread pool (combined with Future/Callable)
[转帖]嫁人一定要嫁工资至少比你高3571.4元的男士
嵌入式系统:基本定时器
RedisTemplate: 报错template not initialized; call afterPropertiesSet() before using it
在ASP控制数字及字母输入
8.4 Summary of the mock competition
tear apart loneliness
复现一次循环和两次循环
【无标题】长期招聘硬件工程师-深圳宝安
ps怎么把图片变清晰,自学ps软件photoshop2022,简单快速用ps让照片更清晰更有质感
SVG big fish eat small fish animation js special effects
【每日一题】1403. 非递增顺序的最小子序列
双向循环带头链表
利用Jenkins的持续集成
v-if/v-else determines whether to display according to the calculation
高效使用数码相机的诀窍
Long-term recruitment embedded development-Shenzhen Baoan









