• [六省联考2017]相逢是问候


    Informatik verbindet dich und mich

    Informatik verbindet dich und mich

    扩展欧拉定理+线段树。

    Informatik verbindet dich und mich

    由扩展欧拉定理得,cc...最终上面的指数必定变成1.(不会打这个东西。。。)

    最多取log次就会变成1,然后就没用了。

    我们每次算的时候再快速幂的话时间复杂度是貌似不能过的。好像是nlog^3n

    至少我加了N发卡常还是过不了。

    但是我们通过题解发现实际上每次快速幂的底数都是一样的,指数也差不多,就可以预处理。

    但是mod的最大值可能达到1e8.

    所以我们预处理1-1e4的,然后再预处理c1e4的1-1e4的。

    最后时间复杂度就去了一个log,不用卡常也过了。

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N=100005;
    inline char gc(){
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    //#define gc getchar
    inline int rd() {
        register int x=0;register char ch=gc();
        while(!isdigit(ch)) ch=gc();
        while(isdigit(ch)) {x=x*10ll+(ch^48);ch=gc();}
        return x;
    }
    struct Segtree{
       int sum;int  l,r;short tag;
    }t[N<<2];
    int a[N],phi[N],n,m,p,c,lim,l,r,low_er[50005][105],high_er[50005][105],f[50005][105];
    bool flag;
    int ksm(int z,int mod) {
        if(z<=10000) return low_er[z][mod];
        return 1ll*high_er[z/10000][mod]*low_er[z%10000][mod]%phi[mod];
    }
    int ksm(long long d,int z,int mod) {
        long long res=1ll;
        while(z) {
            if(z&1) res=res*d;
            d=d*d;
            if(res>=mod) res%=mod;
            if(d>=mod) d%=mod;
            z>>=1;
        }
        return res;
    }
    int work(int d,int z) {
        int res=d;
        if(res>=phi[z]) res=res%phi[z]+phi[z];
        while(z) {
            flag=0;
            res=ksm(res,phi[z-1]);
            if(flag) res+=phi[z-1];
            z--;
        }
        return res;
    }
    #define ls (cur<<1)
    #define rs (cur<<1|1)
    #define mid (l+r>>1)
    void build(int l,int r,int cur){
        t[cur].l=l,t[cur].r=r;
        if(l==r) {
            t[cur].sum=a[l];
            return;
        }
        build(l,mid,ls);
        build(mid+1,r,rs);
        t[cur].sum=(t[ls].sum+t[rs].sum)%p;
    }
    void update(int cur) {
        if(t[cur].tag>=lim) return;
        if(l>t[cur].r||r<t[cur].l) return;
        if(t[cur].l==t[cur].r) {
            t[cur].tag++;
            t[cur].sum=f[t[cur].l][t[cur].tag];
            return;
        }
        update(ls);
        update(rs);
        t[cur].sum=(t[ls].sum+t[rs].sum)%p;
        t[cur].tag=min(t[ls].tag,t[rs].tag);
    }
    long long query(int cur) {
        if(l>t[cur].r||r<t[cur].l) return 0;
        if(l<=t[cur].l&&t[cur].r<=r) return t[cur].sum;
        return (query(ls)+query(rs))%p;
    }
    #undef ls
    #undef rs
    #undef mid
    int getphi(long long x) {
        int res=x,sq=sqrt(x);
        for(int i=2;i<=sq;i++) {
            if(!(x%i)) {
                while(!(x%i)) x/=i;
                res=res/i*(i-1);
            }
        }
        if(x-1) res=res/x*(x-1);
        return res;
    }
    int cal(int x,int num,int d) {
        if(!num) return x%phi[d];
        int t=cal(x,num-1,d+1);
        if(pow(c,num-1)*x>=phi[d+1]) t+=phi[d+1];
        return ksm(t,d);
    }
    void pre() {
        for(int i=0;i<=10000;i++) {
            for(int j=0;j<=lim;j++) {
                low_er[i][j]=ksm(c,i,phi[j]);
                high_er[i][j]=ksm(ksm(c,10000,phi[j]),i,phi[j]);
            }
        }
        for(int i=1;i<=n;i++) {
            if(!a[i]) {
                f[i][1]=1;
                for(int j=2;j<=lim;j++) {
                    f[i][j]=cal(1,j-1,0);
                }
            }
            else for(int j=1;j<=lim;j++) f[i][j]=cal(a[i],j,0);
        }
    }
    signed main() {
        n=rd();m=rd(),p=rd();c=rd();
        phi[0]=p;
        while(phi[lim]^1) lim++,phi[lim]=getphi(phi[lim-1]);
        phi[++lim]=1;
        for(int i=1;i<=n;i++) a[i]=rd();
        pre();
        build(1,n,1);
        int opt;
        while(m--) {
            opt=rd();l=rd();r=rd();
            switch (opt) {
                case 0: {update(1);break;}
                case 1: {printf("%d
    ",query(1));break;}
            }
        }
        return 0;
    }
    相逢是问候
    我是咸鱼。转载博客请征得博主同意Orz
  • 相关阅读:
    博世传感器调试笔记(一)----加速度传感器BMA253
    博世传感器调试笔记(二)加速度及陀螺仪传感器BMI160
    如何分区硬盘
    " " 与" " 区别
    SPI、I2C、UART、I2S、GPIO、SDIO、CAN
    nandflash,norflash,sdram,emmc,rom,ram等各种存储器识别
    AAC音频格式详解
    【转载】音频基础知识
    指针数组和数组指针的区别
    关于720p和1080p观看距离和效果
  • 原文地址:https://www.cnblogs.com/sdfzhsz/p/9748168.html
Copyright © 2020-2023  润新知