bzoj4869 [Shoi2017]相逢是问候

Posted 逢山开路 遇水架桥

tags:

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

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4869

【题解】

发现好像没有办法普通维护。

给小盆友们江数论的时候江过x^m mod p = x^(m mod phi(p)) mod p

发现一个数进行phi操作最多log次。

暴力就行啦qwq

注意就是phi的那个最后要补一个phi[++pn] = 1。

为什么呢?因为phi(1) = 1(展开到最后,还要多展开一层(!))

那么就行啦!

复杂度不大会分析qwq

照理性分析可能是log方到log三方之间的啦

反正跑的……挺快

技术分享
# include <stdio.h>
# include <string.h>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10;

# define RG register
# define ST static

int n, m, p, c, a[M], phi[M], pn;

inline int pwr(int a, int b, int p) {
    int ret = 1;
    while(b) {
        if(b&1) ret = 1ll * ret * a % p;
        a = 1ll * a * a % p;
        b >>= 1;
    }
    return ret;
}

inline int getphi(int n) {
    int ret = n;
    for (int i=2; i*i<=n; ++i) {
        if(n%i!=0) continue;
        ret = ret/i*(i-1);
        while(n%i==0) n/=i;
    }
    if(n!=1) ret=ret/n*(n-1);
    return ret;
}

inline int calc(int x, int p) {
    int ret = x;
    if(ret >= phi[p]) ret = ret % phi[p] + phi[p];
    while(p--) {
        x = ret;
        ret = pwr(c, x, phi[p]); 
        if(p && !ret) ret += phi[p]; 
    }
    return ret % phi[0];
}

namespace SMT {
    # define ls (x<<1)
    # define rs (x<<1|1) 
    int v[M], tms[M];
    inline void build(int x, int l, int r) {
        if(l==r) {
            v[x] = a[l] % phi[0];
            tms[x] = 0; 
            return ;
        }
        int mid = l+r>>1;
        build(ls, l, mid);
        build(rs, mid+1, r);
        v[x] = (v[ls]+v[rs])%phi[0];
        tms[x] = min(tms[ls], tms[rs]);
    }
    inline void change(int x, int l, int r, int L, int R) {
        if(tms[x] >= pn) return;
        if(l == r) {
            tms[x] ++;
            v[x] = calc(a[l], tms[x]);
            return ;
        }
        int mid = l+r>>1;
        if(L <= mid) change(ls, l, mid, L, R);
        if(R > mid) change(rs, mid+1, r, L, R);
        v[x] = (v[ls]+v[rs])%phi[0];
        tms[x] = min(tms[ls], tms[rs]);
    }
    inline int query(int x, int l, int r, int L, int R) {
        if(L <= l && r <= R) return v[x];
        int mid = l+r>>1, re=0;
        if(L <= mid) re += query(ls, l, mid, L, R);
        if(R > mid) re += query(rs, mid+1, r, L, R);
        return re%phi[0];
    }
    # undef ls
    # undef rs
}

int main() {
    scanf("%d%d%d%d", &n, &m, &p, &c);
    for (int i=1; i<=n; ++i) scanf("%d", a+i); 
    phi[0] = p; 
    while(p != 1) {
        int t = getphi(p);
        phi[++pn] = t;
        p = t;
    }
    phi[++pn] = 1;
    SMT::build(1, 1, n); 
    int opt, l, r;
    while(m--) {
        scanf("%d%d%d", &opt, &l, &r);
        if(opt==0) SMT::change(1, 1, n, l, r); 
        else printf("%d\n", SMT::query(1, 1, n, l, r));
    }
    return 0;
}
View Code

 

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

bzoj4869 [Shoi2017]相逢是问候

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

Bzoj4869: [Shoi2017]相逢是问候

bzoj4869 [Shoi2017]相逢是问候

bzoj 4869: [Shoi2017]相逢是问候

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