1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| #include <bits/stdc++.h> #define MAX_N 50000 #define mid ((s+t)>>1) using namespace std; typedef long long lnt; template <class T> inline void read(T &x) { x = 0; int c = getchar(), f = 1; for (; !isdigit(c); c = getchar()) if (c == 45) f = -1; for (; isdigit(c); c = getchar()) (x *= 10) += f*(c-'0'); } int n, m, p, c, k; int a[MAX_N+5]; lnt phi[MAX_N+5]; lnt tr[MAX_N<<2]; int num[MAX_N<<2]; int getphi(int n) { int ret = n; for (int i = 2; i*i <= n; i++) if (n%i == 0) { ret = ret/i*(i-1); while (n%i == 0) n /= i; } if (n^1) ret = ret/n*(n-1); return ret; } lnt pow(lnt x, lnt k, lnt MOD) { lnt ret = 1; for (; k; k >>= 1, x = 1LL*x*x%MOD) if (k&1) ret = 1LL*x*ret%MOD; return ret; } lnt calc(lnt x, int k) { for (int i = k; i; i--) { if (x >= phi[i]) x = x%phi[i]+phi[i]; x = pow(c, x, phi[i-1]), x = x ? x : phi[i-1]; } return x; } void build(int v, int s, int t) { if (s == t) {tr[v] = a[s]%p; return;} build(v<<1, s, mid), build(v<<1|1, mid+1, t); tr[v] = (tr[v<<1]+tr[v<<1|1])%p; } void modify(int v, int s, int t, int l, int r) { if (num[v] >= k) return; if (s == t) {tr[v] = calc(a[s], ++num[v]); return;} if (l <= mid) modify(v<<1, s, mid, l, r); if (r >= mid+1) modify(v<<1|1, mid+1, t, l, r); tr[v] = (tr[v<<1]+tr[v<<1|1])%p; num[v] = min(num[v<<1], num[v<<1|1]); } lnt query(int v, int s, int t, int l, int r) { if (s >= l && t <= r) return tr[v]; lnt ret = 0; if (l <= mid) (ret += query(v<<1, s, mid, l, r)) %= p; if (r >= mid+1) (ret += query(v<<1|1, mid+1, t, l, r)) %= p; return ret; } void init() { phi[0] = p; for (int i = p; i^1; ) phi[++k] = i = getphi(i); phi[++k] = 1; } int main() { read(n), read(m), read(p), read(c); for (int i = 1; i <= n; i++) read(a[i]); init(), build(1, 1, n); while (m--) { int opt, l, r; read(opt), read(l), read(r); if (opt == 0) modify(1, 1, n, l, r); if (opt == 1) printf("%lld\n", query(1, 1, n, l, r)); } return 0; }
|