codeforces906D Power Tower(欧拉降幂)

题意:

给一个序列,q个询问,每个询问回答 [l_k, r_k] 区间的幂塔 % m

思路:

由扩展欧拉定理:(图源https://blog.csdn.net/charlie_jilei/article/details/79252689

重定义取模运算,对每个询问递归求解,记忆化欧拉函数的值

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define MOD(a, b) a < b ? a : a % b + b
const ll inf = 0x3f3f3f3f3f3f3f3f;
const ll N = 1e6 + 10;
ll w[N], p, q, n, l, r, pri[N];

map<ll, ll>eul;
ll qpow(ll a, ll b, ll p) {
    ll ans = 1;
    a = MOD(a, p);
    while(b) {
        if(b & 1) ans = MOD(ans * a, p);
        a = MOD(a * a, p);
        b >>= 1;
    }
    return MOD(ans, p);
}

void init() {
    eul.clear();
    memset(pri, 0, sizeof(pri));
    for(ll i = 2; i < N; ++i) {
        if(!pri[i]) pri[++pri[0]] = i;
        for(ll j = 1; j <= pri[0] && pri[j] < N / i; ++j) {
            pri[pri[j] * i] = 1;
            if(i % pri[j] == 0) break;
        }
    }
}

ll factor[N][2];
ll fatCnt;
void getFactors(ll x) {
    fatCnt = 0;
    ll tmp = x;
    for(ll i = 1; pri[i] <= tmp / pri[i]; ++i) {
        factor[fatCnt][1] = 0;
        if(tmp % pri[i] == 0) {
            factor[fatCnt][0] = pri[i];
            while(tmp % pri[i] == 0) {
                factor[fatCnt][1]++;
                tmp /= pri[i];
            }
            fatCnt++;
        }
    }
    if(tmp != 1) {
        factor[fatCnt][0] = tmp;
        factor[fatCnt++][1] = 1;
    }
}

ll euler(ll n) {
    if(eul[n]) return eul[n];
    getFactors(n);
    ll ret = n;
    for(ll i = 0; i < fatCnt; ++i)
        ret = ret / factor[i][0] * (factor[i][0] - 1);
    eul[n] = ret;
    return ret;
}

ll solve(ll l, ll r, ll mod)
    if(l == r || mod == 1) {
        return MOD(w[r], mod);
    return qpow(w[l], solve(l + 1, r, euler(mod)), mod);
}

int main() {
    init();
    scanf("%lld%lld", &n, &p);
    for(ll i = 1; i <= n; ++i) scanf("%lld", &w[i]);
    scanf("%lld", &q);
    for(ll i = 1; i <= q; ++i) {
        scanf("%lld%lld", &l, &r);
        printf("%lld\n", solve(l, r, p) % p);
    }
	return 0;
}
/*
10 20
792708224 4633945 600798790 384332600 283309209 762285205 750900274 160512987 390669628 205259431
10
5 9
10 10
8 10
7 10
7 10
10 10
4 4
10 10
7 7
4 8
*/

猜你喜欢

转载自blog.csdn.net/weixin_43871207/article/details/109956483