TJOI2018 数学计算

有点意思的题目,这个转化挺有趣的

Description

link

小豆现在有一个数x,初始值为11.小豆有QQ次操作,操作有两种类型:

\(1 \space m :x=x \times m\) 输出\(x\%mod ;\)

\(2\;pos=x/\)\(pos\) 次操作所乘的数(保证第 \(pos\) 次操作一定为类型 \(1\) ,对于每一个类型\(1\)的操作至多会被除一次)输出 \(x\%mod\);

Solution

这个题首先要想到转化成线段树处理

乘除都是单点修改,维护一个区间积就好了

第一步还是很巧妙的

Code

#include
using namespace std;
#define int long long
namespace yspm{
    inline int read()
    {
        int res=0,f=1; char k;
        while(!isdigit(k=getchar())) if(k=='-') f=-1;
        while(isdigit(k)) res=res*10+k-'0',k=getchar();
        return res*f;
    }
    const int N=1e5+10; 
    struct node{
        int l,r,val; 
        #define l(p) t[p].l
        #define r(p) t[p].r
        #define val(p) t[p].val
    }t[N<<2];
    int mod,q,opt,x;
    #define cl(x) memset(x,0,sizeof(x))
    inline void build(int p,int l,int r)
    {
        l(p)=l; r(p)=r; 
        if(l==r) return val(p)=1,void();
        int mid=(l+r)>>1; 
        build(p<<1,l,mid); build(p<<1|1,mid+1,r);
        val(p)=val(p<<1)*val(p<<1|1);
        return ;
    }
    inline void change(int p,int x,int d)
    {
        if(x==l(p)&&x==r(p)) return val(p)=d%mod,void();
        int mid=(l(p)+r(p))>>1; 
        if(x<=mid) change(p<<1,x,d); 
        else change(p<<1|1,x,d);
        return val(p)=val(p<<1)%mod*val(p<<1|1)%mod,void();
    }
    inline void work()
    {
        cl(t); q=read(); mod=read(); build(1,1,q); 
        for(int now=1;now<=q;++now)
        {
            opt=read(); x=read(); 
            if(opt==1) change(1,now,x),printf("%lld\n",val(1)%mod);
            else change(1,x,1),printf("%lld\n",val(1)%mod);
        }
        return ;
    }
    signed main()
    {
        int T=read(); while(T--) work();
        return 0;
    }
}
signed main(){return yspm::main();}

你可能感兴趣的:(TJOI2018 数学计算)