luogu P3934 [Ynoi2016] 炸脖龙 I

https://www.luogu.com.cn/problem/P3934
知道几个性质就能做了

  • 拓展欧拉定理 a c m o d    p = a c m o d    ϕ ( p ) + [ c ≥ ϕ ( p ) ] ∗ ϕ ( p ) \large a^c\mod p=a^{c \mod \phi(p)+[c\ge\phi(p)]*\phi(p)} acmodp=acmodϕ(p)+[cϕ(p)]ϕ(p)
  • ϕ ( x ) \phi(x) ϕ(x)嵌套大概log次会变成1(考虑奇数变成偶数,偶数除2)

然后这题那个树状数组维护一下区间加就行了

code:

#include<bits/stdc++.h>
#define N 20000050
#define ll long long
using namespace std;
int prime[N], vis[N], phi[N], tot;
void getphi(int n) {
    phi[1] = 1;
    for(int i = 2; i <= n; i ++) {
        if(!vis[i]) {
            prime[++ tot] = i;
            phi[i] = i - 1;
        }
        for(int j = 1; j <= tot && i * prime[j] <= n; j ++) {
            vis[i * prime[j]] = 1;
            if(i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
            phi[i * prime[j]] = phi[i] * phi[prime[j]];
        }
    }
}

ll t[N];
int n;
#define lowbit(x) (x & -x)
void update(int x, int y) {
    for(; x <= n; x += lowbit(x)) t[x] += y;
}
ll query(int x) {
    ll ret = 0;
    for(; x; x -= lowbit(x)) ret += t[x];
    return ret;
}

int f;
ll qpow(ll x, ll y, int p) {
    f = 0;
    ll ret = 1;
    for( ; y ; ) {
        if(x >= p) f = 1, x %= p;
        if(y & 1) {
            ret = ret * x;
            if(ret >= p) f = 1, ret %= p;
        }
        y >>= 1;
        x = x * x;
    }
    return ret;
}
int m, a[N], b[N];
int main() {
    getphi(N - 45);
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) scanf("%d", &a[i]), update(i, a[i] - a[i - 1]);
    
    while(m --) {
        int o, x, y, z;
        scanf("%d%d%d%d", &o, &x, &y, &z);
        if(o == 1) update(x, z), update(y + 1, - z);
        else {
            int pos = x, p = z;
            b[pos] = z; p = phi[p];
            while(p > 1 && pos < y) {
                b[++ pos] = p;
                p = phi[p];
            }
        //    for(int i = x; i <= pos; i ++) printf(" %d ", b[i]); printf("   %d\n", query(x));
            ll ans = 1;
            for(int i = pos; i >= x; i --) {
                ans = qpow(query(i), ans, b[i]);
                if(f) ans += b[i];
            }
            printf("%lld\n", ans % z);
        }
    }
    return 0;
}
posted @ 2021-09-02 07:14  lahlah  阅读(65)  评论(0编辑  收藏  举报