Luogu P4588 数字计算 题解

Luogu P4588 [TJOI2018] 数字计算 题解

题目描述

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

1 m:将 x 变为 x×m,并输出 xmodM

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

I/O

INPUT

一共有 t 组输入。

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

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

OUTPUT

对于每一个操作,输出一行,包含操作执行后的 xmodM 的值。

样例

INPUT

1
10 1000000000
1 2
2 1
1 2
1 10
2 3
2 4
1 6
1 7
1 12
2 7

OUTPUT

2
1
2
20
10
1
6
42
504
84
提示

对于 20% 的数据,1Q500

对于 100% 的数据,1Q105t5,M1090<m109

题解

0pts思路

按照题目描述,定义一个 x ,计算乘法,输出

会爆 long long

或者用龟速乘,会超时

或者算逆元,题目给出的模数不一定是质数

100pts思路

既然是对一个数进行数次操作,考虑类似的数据结构:对区间统计结果的 线段树

问题:如何将对单个数的操作调整为对区间的操作?

解答:考虑将时间轴作为区间,初始值为 1 ,统计方案为相乘。操作 1 可以转化为对应的单点修改,操作 2 可以转化为将对应的点修改为 1

代码:

#include<bits/stdc++.h>
using namespace std;
//懒人包
#define GO(u,v,i) for(int i=u;i<=v;i++)
#define mi int mid=(l+r)>>1
//快读快写
template<class t>inline t fr(){
    register t num=0,dis=1;
    register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')dis=-1;ch=getchar();}
    //位运算加速
    while(ch>='0'&&ch<='9'){num=(num<<1)+(num<<3)+(ch^48);ch=getchar();}
    return num*dis;
}
template<class t>inline void fw(t num){
    if(num>9)fw(num/10);
    putchar(num%10+'0');
}
template<class t>inline void fw(t num,char ch){
    //统一判断正负
    if(num<0)num=-num,putchar('-');
    fw(num);putchar(ch);
}
//数据较大,用long long
typedef long long lld;
const int maxn=1e5+12;
lld n,mo;//n即题目中的Q,mo即题目中的M
lld t[maxn<<1];
int lson[maxn<<1],rson[maxn<<1];//(伪)动态开点
int tot;
inline void Pushup(int k){
    t[k]=(t[lson[k]]*t[rson[k]])%mo;
}
inline void build(int l,int r,int &k){
    k=++tot;
    if(l==r){
    	t[k]=1;return;
	}
	mi;
	build(l,mid,lson[k]);
    build(mid+1,r,rson[k]);
    Pushup(k);
}
inline void update(int l,int r,int v,int x,int k){
    if(l==r){
        t[k]=x;return;
    }
    mi;
    if(v<=mid)update(l,mid,v,x,lson[k]);
    else update(mid+1,r,v,x,rson[k]);
    Pushup(k);
}
signed main(){
    int ti=fr<int>();
    while(ti--){
        n=fr<int>();mo=fr<int>();
        int temp=0;tot=0;
        build(1,n,temp);
        GO(1,n,i){
            int a=fr<int>(),b=fr<int>();
            if(a==1){
                update(1,n,i,b,1);
                fw(t[1],'\n');
            }else{
                update(1,n,b,1,1);
                fw(t[1],'\n');
            }
        }
    }
    return 0;
}
posted @   Locked_Fog  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
主题色彩