思路一:直接模拟(会因为爆 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; }