bzoj4869 [Shoi2017]相逢是问候

Posted poorpool

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4869 [Shoi2017]相逢是问候相关的知识,希望对你有一定的参考价值。

可以发现, \[\displaystyle c^{c^{c^\cdots}}\] 从下到上对应的模数是 \(p,\varphi(p),\varphi(\varphi(p)),\varphi(\varphi(\varphi(p))),\ldots ,1,1\)。(为什么有两个 \(1\)?一会儿再说)

因此当一个数被修改了很多次以后它就不会再变了,维护一下一个数被修改了几次。

再来说为什么两个 \(1\)。以 \(n=1,p=3,a_1=0,c=2\) 为例:

\[2^{2^0} \bmod 3=2,2^{2^{2^0}} \bmod 3=1\]

这是由于扩展欧拉定理得到的。也就是说,

\[2^{2^{0 \bmod 1} \bmod 2} \bmod 3=2,\]

\[2^{2^{2^{0 \bmod 1}\bmod 1 + 1}\bmod 2}\bmod 3=1.\]

这就造成了在 \(\bmod 1\) 时的不同。如果只有一个 \(1\),会造成上下等价。其实,这是一组非常特殊的数据。

懒得卡常了,以下代码仅能 A bzoj。

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int n, m, p, c, phi[105], cnt, a[50005], opt, uu, vv;
bool isy;
struct SGT{
    int sum[200005], tag[200005];
    void build(int o, int l, int r){
        if(l==r)    sum[o] = a[l];
        else{
            int mid=(l+r)>>1;
            int lson=o<<1;
            int rson=lson|1;
            if(l<=mid)  build(lson, l, mid);
            if(mid<r)   build(rson, mid+1, r);
            sum[o] = (sum[lson] + sum[rson]) % p;
        }
    }
    int ksm(int a, int b, int p){
        int re=1;
        while(b){
            if(b&1){
                if((ll)re*a>=p) isy = true;
                re = ((ll)re * a) % p; 
            }
            if(b!=1 && (ll)a*a>=p)  isy = true;
            a = ((ll)a * a) % p;
            b >>= 1;
        }
        return re;
    }
    int changeOneEle(int x, int hmn){
        int tmp=x;
        if(tmp>phi[hmn])    tmp = tmp%phi[hmn] + phi[hmn];
        for(int i=hmn-1; i>=0; i--){
            isy = false;
            tmp = ksm(c, tmp, phi[i]);
            if(isy) tmp += phi[i];
        }
        return tmp%p;
    }
    void update(int o, int l, int r, int x, int y){
        if(tag[o]>=cnt-1)   return ;
        if(l==r)
            sum[o] = changeOneEle(a[l], ++tag[o]);
        else{
            int mid=(l+r)>>1;
            int lson=o<<1;
            int rson=lson|1;
            if(x<=mid)  update(lson, l, mid, x, y);
            if(mid<y)   update(rson, mid+1, r, x, y);   
            sum[o] = (sum[lson] + sum[rson]) % p;
            tag[o] = min(tag[lson], tag[rson]);
        }
    }
    int query(int o, int l, int r, int x, int y){
        if(l>=x && r<=y)    return sum[o];
        else{
            int mid=(l+r)>>1;
            int lson=o<<1;
            int rson=lson|1;
            int re=0;
            if(x<=mid)  re = (re + query(lson, l, mid, x, y)) % p;
            if(mid<y)   re = (re + query(rson, mid+1, r, x, y)) % p;
            return re;
        }
    }
}sgt;
int getPhi(int x){
    int re=x;
    for(int i=2; i*i<=x; i++)
        if(x%i==0){
            re = re / i * (i - 1);
            while(x%i==0)   x /= i;
        }
    if(x>1) re = re / x * (x - 1);
    return re;
}
void prePhi(){
    phi[cnt++] = p;
    while(phi[cnt-1]!=1){
        phi[cnt] = getPhi(phi[cnt-1]);
        cnt++;
    }
    phi[cnt++] = 1;
}
int main(){
    cin>>n>>m>>p>>c;
    for(int i=1; i<=n; i++)
        scanf("%d", &a[i]);
    sgt.build(1, 1, n);
    prePhi();
    while(m--){
        scanf("%d %d %d", &opt, &uu, &vv);
        if(opt==0)  sgt.update(1, 1, n, uu, vv);
        else    printf("%d\n", sgt.query(1, 1, n, uu, vv));
    }
    return 0;
}

以上是关于bzoj4869 [Shoi2017]相逢是问候的主要内容,如果未能解决你的问题,请参考以下文章

bzoj4869 [Shoi2017]相逢是问候

BZOJ4869:[SHOI2017]相逢是问候——题解

Bzoj4869: [Shoi2017]相逢是问候

bzoj4869 [Shoi2017]相逢是问候

bzoj 4869: [Shoi2017]相逢是问候

bzoj4869[Shoi2017]相逢是问候 线段树+扩展欧拉定理