您的位置:首页 > 其它

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

2017-01-03 19:33 471 查看

题意

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

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

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

#include <cstdio>
#define N 100010

int n,m,p,A
,app
,op,l,r,ic
,ced
;

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: