zoukankan      html  css  js  c++  java
  • bzoj:4105: [Thu Summer Camp 2015]平方运算

    Description

     

    Input

    第一行有三个整数N,M,p,分别代表序列的长度、平方操作与询问操作的总次数以及在平方操作中所要模的数。

     
    接下来一行N个数代表一开始的序列{X1,X2,...,XN}。
     
    接下来M行,每行三个整数op,l,r。其中op代表本次操作的类型。若op=0,代表这是一次平方操作,平方的区间为[l,r];如果op=1,代表这是一次询问操作,询问的区间为[l,r]。
     

    Output

    对于每次的询问操作,输出一行代表这段区间内数的总和。注意:答案没有对任何数取模。

     

    Sample Input

    3 3 11
    1 2 3
    1 1 3
    0 1 3
    1 1 3

    Sample Output

    6
    14

    HINT

     对于100%的数据,∀i,Xi∈[0,p),l,r∈[1,n]


    N,M,p的范围如下:

     

    编号  N  M  p

    1  1000  1000  233

    2  1000  1000  2332

    3  100000  100000  5

    4  100000  100000  8192

    5  100000  100000  23

    6  100000  100000  45

    7  100000  100000  37

    8  55000  55000  4185

    9  55000  55000  5850

    10  55000  55000  2975

    11  55000  55000  2542

    12  55000  55000  2015

    13  60000  60000  2003

    14  65000  65000  2010

    15  70000  70000  4593

    16  75000  75000  4562

    17  80000  80000  1034

    18  85000  85000  5831

    19  90000  90000  9905

    20  100000  100000  9977
     
    膜了一大把题解
    线段树是肯定的……
    平方是会出现循环节的(听说会很短
    预处理出所有环,和指向环的链,由于没有其他修改操作,这里面的数字肯定是越修改越往环跑,进了环就处理出跑k次后答案是多少,不在环上就暴力改……
    论权限号的重要性
    /**************************************************************
        Problem: 4105
        User: JSZX11556
        Language: C++
        Result: Accepted
        Time:25216 ms
        Memory:275236 kb
    ****************************************************************/
     
    #include<cstdio>
    #include<algorithm>
    #define lp (p<<1)
    #define rp ((p<<1)|1)
    using namespace std;
     
    int read_p,read_ca;
    inline int read(){
        read_p=0;read_ca=getchar();
        while(read_ca<'0'||read_ca>'9') read_ca=getchar();
        while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
        return read_p;
    }
    int n,m,p,a[100001],ne[100001],i;
    bool v[100001],f[100001];
    struct na{
        int l,r,w,le,c,b[63],pos;
        bool v;
    }t[1000000];
    inline int gcd(int x,int y){return y==0?x:gcd(y,x%y);}
    inline int lcm(int x,int y){return x*y/gcd(x,y);}
    inline void updata(int p){
        if (t[p].l==t[p].r) return;
        t[p].w=t[lp].w+t[rp].w;
        t[p].v=t[lp].v&t[rp].v;
        if (t[p].v){
            t[p].pos=0;
            t[p].le=lcm(t[lp].le,t[rp].le);
            for (i=0;i<t[p].le;i++) t[p].b[i]=t[lp].b[(i+t[lp].pos)%t[lp].le]+t[rp].b[(i+t[rp].pos)%t[rp].le];
        }
    }
    inline void build(int p,int l,int r){
        t[p].l=l;t[p].r=r;
        if (l==r){
            t[p].w=a[l];t[p].v=f[t[p].w];
            if (t[p].v) for (t[p].b[0]=t[p].w,t[p].le=1,i=ne[t[p].w];i!=t[p].w;i=ne[i]) t[p].b[t[p].le++]=i;
            return;
        }
        int mid=l+r>>1;
        build(lp,l,mid);build(rp,mid+1,r);
        updata(p);
    }
    inline void hb(int p,int c){
        if (!t[p].v){
            for (i=1;i<=c;i++) t[p].w=ne[t[p].w];t[p].v=f[t[p].w];
            if (t[p].v) for (t[p].b[0]=t[p].w,t[p].le=1,i=ne[t[p].w];i!=t[p].w;i=ne[i]) t[p].b[t[p].le++]=i;
            return;
        }
        c%=t[p].le;
        t[p].c+=c;if (t[p].c>=t[p].le) t[p].c-=t[p].le;
        t[p].pos+=c;if (t[p].pos>=t[p].le) t[p].pos-=t[p].le;
        t[p].w=t[p].b[t[p].pos];
    }
    inline void pd(int p){
        if (t[p].c){
            if (t[p].l!=t[p].r) hb(lp,t[p].c),hb(rp,t[p].c);
            t[p].c=0;
            updata(p);
        }
    }
    inline void ch(int p,int l,int r){
        if (t[p].l==l&&t[p].r==r&&t[p].v) return hb(p,1);
        pd(p);
        if (t[p].l==t[p].r){
            t[p].w=ne[t[p].w];t[p].v=f[t[p].w];
            if (t[p].v) for (t[p].b[0]=t[p].w,t[p].le=1,i=ne[t[p].w];i!=t[p].w;i=ne[i]) t[p].b[t[p].le++]=i;
            return;
        }
        int mid=t[p].l+t[p].r>>1;
        if (r<=mid) ch(lp,l,r);else
        if (l>mid) ch(rp,l,r);else
        ch(lp,l,mid),ch(rp,mid+1,r);
        updata(p);
    }
    inline int MMH(int p,int l,int r){
        pd(p);
        if (t[p].l==l&&t[p].r==r) return t[p].w;
        int mid=t[p].l+t[p].r>>1;
        if (r<=mid) return MMH(lp,l,r);else
        if (l>mid) return MMH(rp,l,r);else
        return MMH(lp,l,mid)+MMH(rp,mid+1,r);
    }
    int main(){
        register int i,j,T,l,r;
        n=read();m=read();
        p=read();
        for (i=1;i<=n;i++) a[i]=read();
        for (i=0;i<p;i++) ne[i]=i*i%p,f[i]=1;
        for (i=0;i<p;i++)
        if (!v[i]){
            for (j=i;!v[j];j=ne[j]) v[j]=1;
            for (T=i;T!=j;T=ne[T]) f[T]=0;
        }
        build(1,1,n);
        for (i=1;i<=m;i++){
            T=read();l=read();r=read();
            if (T)printf("%d
    ",MMH(1,l,r));else ch(1,l,r);
        }
    }
    
    View Code
  • 相关阅读:
    java 基本数据类型的取值范围
    警惕自增的陷阱
    三元操作符的类型务必一致
    不要随便设置随机种子
    优先使用整形池
    IN、ANY、ALL与SOME
    第六章-序列:字符串、列表和元组 笔记
    第十二章-安全性
    第五章-数字 课后答案
    第十一章-约束、视图与事务
  • 原文地址:https://www.cnblogs.com/Enceladus/p/5510247.html
Copyright © 2011-2022 走看看