[BZOJ4105][Thu Summer Camp 2015]平方运算

来源:互联网 发布:淘宝上电动涡轮增压器 编辑:程序博客网 时间:2024/06/05 18:09

题意


给定一个数列,有两种操作,询问一段区间[l,r]内的和或者对于i[l,r]xi=xi 2%p


类似于[bzoj3038]上帝造题的七分钟的思想

因为存在取模,所以xi变成xi 2%p一定会存在循环,又因为p给的比较特殊,循环的大小也比较小,所以可以对于处在循环中的数打标记,不处在循环中的数暴力。

#include <cstdio>#define N 100010int n,m,p,A[N],app[N],op,l,r,ic[N],ced[N];struct bt{    int l,r,x[100],sz,bg,bic,sum,w;}T[N<<2];inline void reaD(int &x){    char Ch=getchar();x=0;    for(;Ch>'9'||Ch<'0';Ch=getchar());    for(;Ch>='0'&&Ch<='9';x=x*10+Ch-'0',Ch=getchar());}inline void upd(int g){    T[g].sum=T[g<<1].sum+T[g<<1|1].sum;    if(!T[g<<1].bic||!T[g<<1|1].bic)return;    int i=T[g<<1].bg,j=T[g<<1|1].bg;T[g].bic=1;    T[g].bg=1;T[g].sz=0;    do{        T[g].x[++T[g].sz]=T[g<<1].x[i]+T[g<<1|1].x[j];        if((++i)>T[g<<1].sz)i=1;        if((++j)>T[g<<1|1].sz)j=1;    }while(i!=T[g<<1].bg||j!=T[g<<1|1].bg);}void buc(int g,int l){    T[g].bic=1;    app[T[g].x[T[g].sz=1]=A[l]]=l;T[g].bg=1;    while(l!=app[(T[g].x[T[g].sz]*T[g].x[T[g].sz])%p]){        app[(T[g].x[T[g].sz]*T[g].x[T[g].sz])%p]=l;        T[g].x[++T[g].sz]=(T[g].x[T[g].sz-1]*T[g].x[T[g].sz-1])%p;    }    T[g].sum=T[g].x[T[g].bg];}void build(int g,int l,int r){    T[g].l=l;T[g].r=r;    if(l==r){        T[g].sum=A[l];        if(!ic[A[l]]) return;        buc(g,l);        return ;    }    int mid=l+r>>1;    build(g<<1,l,mid);build(g<<1|1,mid+1,r);    upd(g);}inline void down(int g){    if(T[g].w){        T[g<<1].sum=T[g<<1].x[++((T[g<<1].bg+=T[g].w-1)%=T[g<<1].sz)];        T[g<<1|1].sum=T[g<<1|1].x[++((T[g<<1|1].bg+=T[g].w-1)%=T[g<<1|1].sz)];        T[g<<1].w+=T[g].w;T[g<<1|1].w+=T[g].w;        T[g].w=0;    }}void update(int g,int l,int r){    if(T[g].l==l&&T[g].r==r){        if(T[g].bic){if((++T[g].bg)>T[g].sz)T[g].bg=1;T[g].sum=T[g].x[T[g].bg];T[g].w++;return;}        if(l==r){            if(ic[(A[l]*=A[l])%=p])buc(g,l);            T[g].sum=A[l];            return;        }        down(g);        int mid=T[g].l+T[g].r>>1;        update(g<<1,T[g].l,mid);        update(g<<1|1,mid+1,T[g].r);        upd(g);        return;    }    down(g);    int mid=T[g].l+T[g].r>>1;    if(r<=mid) update(g<<1,l,r); else    if(l>mid) update(g<<1|1,l,r); else    update(g<<1,l,mid),update(g<<1|1,mid+1,r);    upd(g);}int query(int g,int l,int r){    if(T[g].l==l&&T[g].r==r)return T[g].sum;    down(g);    int mid=T[g].l+T[g].r>>1;    if(r<=mid) return query(g<<1,l,r);    if(l>mid) return query(g<<1|1,l,r);    return query(g<<1,l,mid)+query(g<<1|1,mid+1,r);}void dfs(int x){    if(ic[x]) return;    int k=x;    ced[x]=k;x=x*x%p;    while(ced[x]!=k){        ced[x]=k;        x=x*x%p;    }    int y=x;ic[x]=1;x=x*x%p;    while(x!=y){        ic[x]=1;        x=x*x%p;    }}int w[20],wt;inline void Pt(int x){    if(!x){putchar(48);putchar('\n');return;}    while(x)w[++wt]=x%10,x/=10;    for(;wt;wt--)putchar(w[wt]+48);putchar('\n');}int main(){    freopen("1.in","r",stdin);    freopen("1.out","w",stdout);    reaD(n);reaD(m);reaD(p);    for(int i=0;i<p;i++) dfs(i);    for(int i=1;i<=n;i++) reaD(A[i]);    build(1,1,n);    for(int i=1;i<=m;i++){        reaD(op);reaD(l);reaD(r);        if(op==0) update(1,l,r);        else Pt(query(1,l,r));    }    return 0;}
0 0
原创粉丝点击