[TJOI2018]數學計算

Young_Zn_Cu發表於2020-10-28

[TJOI2018]數學計算

思路一:直接模擬(會因為爆 l o n g   l o n g long\ long long long的問題導致程式碼非常複雜)

思路二:考慮線段樹。建立一棵線段樹,其葉子節點都是對應的乘數,每個非葉子節點的值為其左右兒子的值的乘積對 mod \text{mod} mod 取模的值。這樣,任意時候都有 x = x= x=該線段樹的根的值。操作 1 1 1可以直接上,操作 2 2 2可以看做是把第 t t t次的乘數改為 1 1 1。然後考慮使用線段樹分治的思想處理即可。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=100000+50;
inline int read(){
	int cnt=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}
	while(isdigit(c)){cnt=(cnt<<3)+(cnt<<1)+(c^48);c=getchar();}
	return cnt*f;
}
struct tree{int val;}tr[N<<2];
int q,mod,t,op,m;
inline void pushup(int p){tr[p].val=(tr[p<<1].val%mod*tr[p<<1|1].val%mod)%mod;}
void build(int p,int l,int r){
	if(l==r) {tr[p].val=1;return;}
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	pushup(p);
	return;
}
void modify(int p,int l,int r,int x,int v){
	if(l==r) {tr[p].val=v;return;}
	int mid=(l+r)>>1;
	if(x<=mid) modify(p<<1,l,mid,x,v);
	else modify(p<<1|1,mid+1,r,x,v);
	pushup(p);return;
}
signed main(){
	t=read();
	while(t--){
		q=read(),mod=read();build(1,1,q);
		for(int i=1;i<=q;++i){
			op=read();m=read();
			if(op==1) modify(1,1,q,i,m),printf("%lld\n",tr[1].val);
			else modify(1,1,q,m,1),printf("%lld\n",tr[1].val);
		}
	}
	return 0;
}

相關文章