• [Shoi2017]相逢是问候


    传送门

    这种“暴力线段树”可以考虑一下是不是有什么特殊性质。

    对于这道题什么要知道:

     可能这里写得比较清楚(摘自

    感觉就是一个迭代的过程。

    而一个数在操作k次之后就可以不用再操作了。

    然后使用欧拉定理的时候要特判一下:

    x>=phi时,最后要加一个phi

    小于则不加。

     

     预处理出所有的phi,记得最后一个phi为1。

    #include<bits/stdc++.h>
    #define LL long long
    #define N 50003
    using namespace std;
    int read()
    {
        int x=0,f=1;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x*f;
    }
    LL n,m,p,c;
    LL num=0;
    LL a[N],P[N];
    int ok=0;
    LL quick(LL a,LL x,LL mod)
    {
        LL ans=1;
        while(x)
        {
            if(x&1)ans=ans*a;
            a=a*a;x>>=1;
            if(ans>=mod)ok=1,ans%=mod;
            if(a>=mod)ok=1,a%=mod;
        }
        return ans;
    }
    int phi(int x)
    {
        int ans=x;
        for(int i=2;i*i<=x;++i)
        {
            if(x%i==0)
            {
                ans=ans/i*(i-1);
                while(x%i==0)x/=i;
            }
        }
        if(x!=1)ans=ans/x*(x-1);
        return ans; 
    }
    LL sum[N<<2],ge[N<<2];
    void pushup(int k)
    {
        sum[k]=(sum[k<<1]+sum[k<<1|1])%p;
        ge[k]=min(ge[k<<1],ge[k<<1|1]);
    }
    void build(int k,int l,int r)
    {
        if(l==r){sum[k]=a[l]%p;return;}
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        pushup(k);
    }
    LL query(int k,int L,int R,int l,int r)
    {
        LL ans=0;
        if(L>=l&&R<=r)return sum[k];
        int mid=(L+R)>>1;
        if(l<=mid)
        {
            ans+=query(k<<1,L,mid,l,r);
            if(ans>=p)ans%=p;
        }
        if(r>mid)
        {
            ans+=query(k<<1|1,mid+1,R,l,r);
            if(ans>=p)ans%=p;
        }
        return ans%p;
    }
    LL cal(LL x,LL times)
    {
        if(x>P[times]) x=x%P[times]+P[times];
        for(int i=times;i>=1;--i)//类似迭代求解 
        {
            ok=0;//特判一下 
            x=quick(c,x,P[i-1]);
            if(ok) x+=P[i-1];
        } 
        return x;
    }
    void modify(int k,int L,int R,int l,int r)
    {
        if(ge[k]>=num)return;//超过上限次数就不会再变了 
        if(L==R)
        {
            sum[k]=cal(a[L],++ge[k])%p;
            return ;
        } 
        int mid=(L+R)>>1;
        if(l<=mid)modify(k<<1,L,mid,l,r);
        if(r>mid)modify(k<<1|1,mid+1,R,l,r);
        pushup(k);
    }
    int main()
    { 
     // freopen("verbinden.in","r",stdin);
    //  freopen("verbinden.out","w",stdout);
        n=read(),m=read(),p=read(),c=read();
        int q=p;
        num=0;
        P[0]=q;
        while(q!=1)//预处理出phi 
        {
            q=P[++num]=phi(q);
        }
        P[++num]=1;
        int flagg=0;
        for(int i=1;i<=n;++i)a[i]=read();
        build(1,1,n);
        for(int i=1;i<=m;++i)
        {
            int op=read(),l=read(),r=read();
            if(op==0)
            {
                modify(1,1,n,l,r);//a[i]=quick(c,a[i]);
            }
            else if(op==1)
            {
                LL ans=0;
                printf("%lld
    ",query(1,1,n,l,r)%p);
            }
        }
    } 
    View Code
  • 相关阅读:
    QProgressBar的使用例子
    kube框架结构-一个小型响应式CSS框架
    窗口类型(Widget, Window, Dialog, Desktop, SubWindow等等)
    Qt 之 设置窗口边框的圆角(使用QSS和PaintEvent两种方法)
    十大开源游戏引擎深入比较
    一种通用查询语言的定义与实践
    EF分页问题探讨之 OrderBy
    手把手教你做关键词匹配项目
    git
    Extension+NVelocity
  • 原文地址:https://www.cnblogs.com/yyys-/p/11544402.html
Copyright © 2020-2023  润新知