[洛谷3934]P3934 Nephren Ruq Insania题解

先放个奈芙莲

解法
看到这种题目就知道是欧拉降幂,然后根据某玄学证明,递归欧拉降幂从l到r不会超过\(\Theta(log_n)\),所以直接递归解决,然后区间修改直接树状数组维护一下
然后就A了

代码

#include <cstdio>

namespace FenTree{
    #define lowbit(x) (x&(-x))
    #define MAXN 500005
    #define ll long long
    ll BIT[MAXN]; int n;
    void add(int pos, int val){
        for (; pos <= n; pos += lowbit(pos)) BIT[pos] += val;
    }
    ll query(int pos){
        ll sum = 0;
        for (; pos; pos -= lowbit(pos)) sum += BIT[pos];
        return sum;
    }
    void addsec(int l, int r, int val){
        add(l, val);
        if (r < n) add(r + 1, -val);
    }
    #undef ll
    #undef MAXN 
    #undef lowbit
};

namespace IO{
    #define ll long long
    inline ll read(){
        ll x = 0; int zf = 1; char ch = ' ';
        while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
        if (ch == '-') zf = -1, ch = getchar();
        while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
    }
    #undef ll
};

namespace Qpow{
    #define ll long long
    ll pow(ll a, ll b, ll mod){
        if (!a) return 0;
        ll ans = 1;
        for ( ; b; b >>= 1, a = (a * a) % mod)
            if (b & 1)
                ans *= a, ans %= mod;
        return ans;
    }
    ll elrPow(ll x, ll y, ll mod){
        ll res = 1; bool flgres = 0, flgx = 0; 
        for ( ; y; y >>= 1){
            if (y & 1){
                res *= x, flgres = flgx;
                if (res >= mod) res %= mod, flgres = 1;
            }
            if (x >= mod)flgx = 1, x %= mod;
            x *= x;
            if (x >= mod)flgx = 1, x %= mod;
        }
        return flgres ? (res + mod) : res;
    }
    #undef ll
}

int phi[20000005];
int primes[20000005], pcnt;
bool isnp[20000005];

void getPhi(int num){
    phi[1] = 1;
    for (int i = 2; i <= num; ++i){
        if (!isnp[i]) primes[++pcnt] = i, phi[i] = i - 1;
        for (int j = 1; j <= pcnt && i * primes[j] <= num; ++j){
            isnp[i * primes[j]] = 1;
            if (!(i % primes[j])){phi[i * primes[j]] = phi[i] * primes[j]; break;}
            phi[i * primes[j]] = phi[i] * (primes[j] - 1);
        }
    }
}

int a[500005];

long long solve(int l, int r, long long p){
    if (p == 1 || l > r) return 1;
    long long x = FenTree::query(l) + a[l];
    return Qpow::elrPow(x, solve(l + 1, r, phi[p]), p);
}

int main(){
    getPhi(20000000);
    int n = IO::read(), m = IO::read(); FenTree::n = n;
    for (int i = 1; i <= n; ++i) a[i] = IO::read();
    int op, l, r; long long val;
    for (int i = 1; i <= m; ++i){
        op = IO::read(), l = IO::read(), r = IO::read(), val = IO::read();
        if (op == 1) FenTree::addsec(l, r, val);
        else printf("%lld\n", solve(l, r, val) % val);
    }
    return 0;
}
posted @ 2019-05-21 16:00  LinZhengmin  阅读(327)  评论(0编辑  收藏  举报

Contact with me