TJOI2018 数学计算

分析

如果采取暴力的做法,那么乘起来会炸longlong,除非写个高精。
再考虑乘一下逆元呢,显然也不行,模数不一定为质数。
这道题的关键点在于这句话,对于每一个类型1的操作至多会被除一次
这句话的最基本的告诉了我们每次得到的答案一定是一个整数
其次,这句话保证了可以应用线段树解决这个问题
如果除的操作可能会重复,就不能再用线段树了。

#include<cstdio>
#include<cstring>
#include<algorithm>
const int lqs=1e5+10;
int mod;
struct Tree{
	int val,l,r;
}T[lqs<<2];
#define ls rt<<1
#define rs rt<<1|1
void pushup(int rt){
	T[rt].val=1ll*(T[ls].val%mod)*(T[rs].val%mod)%mod;
}
void Build(int rt,int l,int r){
	T[rt].l=l;T[rt].r=r;
	if(l==r){
		T[rt].val=1;
		return ;
	}
	int mid=l+r>>1;
	Build(ls,l,mid);
	Build(rs,mid+1,r);
	pushup(rt);
}
void modify(int rt,int x,int w){
	if(T[rt].l==T[rt].r&&T[rt].l==x){
		T[rt].val=w;
		return ;
	}
	int mid=T[rt].l+T[rt].r>>1;
	if(x<=mid)modify(ls,x,w);
	else modify(rs,x,w);
	pushup(rt);
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int q;
		scanf("%d%d",&q,&mod);
		Build(1,1,q);
		for(int i=1;i<=q;i++){
			int op,x;
			scanf("%d%d",&op,&x);
			if(op==1)
				modify(1,i,x%mod);
			else
				modify(1,x,1);
			printf("%d\n",T[1].val);
		}
	}
	return 0;
}

相关推荐