数学计算,题解

题目连接

分析:

题意很清楚,首先不要没有头绪,我们想一想如果是区间乘%一个数怎么做?直接线段树,然后再看本题,搞一个数组,如果是操作1,对应的数字就是val,操作2对应的就是1,然后对于操作1,就是求1到i的乘积,对于2,直接求1到val-1和val+1到i的乘积.解决问题.

代码:

#include <cstdio>
#define ll long long
const int maxn=1e5+10;
ll mod;
struct TREE{
    ll val;
    int l;
    int r;
    ll lazyp;
    ll lazym;
}tr[maxn*4];
void build(int x,int l,int r){
    tr[x].l=l;
    tr[x].r=r;
    tr[x].lazym=1;
    tr[x].lazyp=0;
    if(l==r){
        tr[x].val=1;
        return;
    }
    int mid=(l+r)/2;
    build(x*2,l,mid);
    build(x*2+1,mid+1,r);
    tr[x].val=(tr[x*2].val*tr[x*2+1].val)%mod;
}
ll cha(int x,int l,int r){
    if(tr[x].l>=l&&tr[x].r<=r)
        return tr[x].val;
    int mid=(tr[x].l+tr[x].r)/2;
    ll ans=1;
    if(l<=mid)
        ans*=cha(x*2,l,r);
    ans%=mod;
    if(r>=mid+1)
        ans*=cha(x*2+1,l,r);
    ans%=mod;
    return ans;
}
void chan(int x,int s,ll ke){
    if(tr[x].l==tr[x].r){
        tr[x].val=ke;
        return;
    }
    int mid=(tr[x].l+tr[x].r)/2;
    if(s<=mid)
        chan(x*2,s,ke);
    if(s>=mid+1)
        chan(x*2+1,s,ke);
    tr[x].val=tr[x*2].val*tr[x*2+1].val%mod;
}
int w[maxn];
ll val[maxn];
int main(){
    int t;
    scanf("%d",&t);
    for(int jsjs=1;jsjs<=t;jsjs++){
        int q;
        scanf("%d%lld",&q,&mod);
        build(1,1,q);
        for(int i=1;i<=q;i++){
            scanf("%d%d",&w[i],&val[i]);
            if(w[i]==1)
                chan(1,i,val[i]);
            else
                chan(1,val[i],1);
            printf("%lld\n",cha(1,1,i)%mod);
        }
    }
    return 0;
}

相关推荐