https://www.luogu.com.cn/problem/P3747
I ca n’t remember the last time I encountered the extended Euler theorem.
\(a^b~mod~p=\)
\(b<\phi(p),a^b~mod~p\)
\(b\ge \phi(p),a^{b~mod~\phi(p)+\phi(p)}~mod~p\)
Suppose the sequence of modulus is always taken as \ (\ phi \) is \ (p [1], p [2],…, p [p0] (p0 \ le 2log_2 (mo)) \)
For this problem, you can record a \ (cnt \) for each number to indicate how many times it has been powed. After \ (cnt> p0 \) , it is the same as the value of \ (cnt = p0 + 1 \)
Note that it is the same value as \ (cnt = p0 + 1 \) . For convenience, open one more bit:p[++p0]=1
Use the line segment tree to maintain the minimum value of the interval \ (cnt \) , if \ (\ le p0 \) , just go ahead and modify it.
Each number needs to be modified \ (log \) times, and each modification requires \ (log ^ 2 \) time to find a new answer (a log comes from a fast power), so that T will be two points.
Note that the numbers are all \ (c \) , so preprocessing \ (c ^ {0..15000} \) and \ (c ^ {0..15000 * 15000} \) in \ (mod \) each \ (p [i] \) under the value, you can \ (O (2) \) fast power.
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
const int N = 50005;
int n, m, sp, c;
int v[N];
int phi(int n) {
if(n == 1) return 1;
int s = n;
for(int x = 2; x * x <= n; x ++) if(n % x == 0) {
s = s / x * (x - 1);
for(; n % x == 0; n /= x);
}
if(n > 1) s = s / n * (n - 1);
return s;
}
int p[N], p0;
namespace sub1 {
struct P {
ll x; int y;
P(ll _x = 0, int _y = 0) {
x = _x, y = _y;
}
};
P mul(P a, P b, int mo) {
a.y |= b.y;
a.x *= b.x;
if(a.x >= mo) a.x %= mo, a.y = 1;
return a;
}
const int M = 15000;
P t1[100][M], t2[100][M];
void build() {
fo(i, 1, p0) {
t1[i][0] = t2[i][0] = P(1 % p[1], 1 >= p[1]);
P w = P(c % p[i], c >= p[i]);
fo(j, 1, M) t1[i][j] = mul(t1[i][j - 1], w, p[i]);
w = t1[i][M];
fo(j, 1, M) t2[i][j] = mul(t2[i][j - 1], w, p[i]);
}
}
P b[N];
ll calc(int *a, int a0) {
a0 = min(a0, p0);
b[a0] = P(a[a0] % p[a0], a[a0] >= p[a0]);
fd(i, a0 - 1, 1) {
int y = b[i + 1].x + (b[i + 1].y ? p[i + 1] : 0);
int z1 = y % M, z2 = y / M;
b[i] = mul(t1[i][z1], t2[i][z2], p[i]);
}
return b[1].x;
}
}
using sub1 :: calc;
int a[N]; int a0;
#define i0 i + i
#define i1 i + i + 1
ll t[N * 4]; int mi[N * 4];
void bt(int i, int x, int y) {
if(x == y) {
t[i] = v[x] % p[1];
return;
}
int m = x + y >> 1;
bt(i0, x, m); bt(i1, m + 1, y);
t[i] = (t[i0] + t[i1]) % p[1];
}
int pl, pr, px;
void add(int i, int x, int y) {
if(mi[i] >= p0 - 1 || y < pl || x > pr) return;
if(x == y) {
mi[i] ++;
a0 = mi[i] + 1;
fo(j, 1, a0 - 1) a[j] = c; a[a0] = v[x];
t[i] = calc(a, a0);
return;
}
int m = x + y >> 1;
add(i0, x, m); add(i1, m + 1, y);
t[i] = (t[i0] + t[i1]) % p[1];
mi[i] = min(mi[i0], mi[i1]);
}
void ft(int i, int x, int y) {
if(y < pl || x > pr) return;
if(x >= pl && y <= pr) {
px = (px + t[i]) % p[1];
return;
}
int m = x + y >> 1;
ft(i0, x, m); ft(i1, m + 1, y);
}
int op;
int main() {
scanf("%d %d %d %d", &n, &m, &sp, &c);
p[p0 = 1] = sp;
while(p[p0] != 1) p0 ++, p[p0] = phi(p[p0 - 1]);
p[++ p0] = 1;
fo(i, 1, n) scanf("%d", &v[i]);
sub1 :: build();
bt(1, 1, n);
fo(ii, 1, m) {
scanf("%d %d %d", &op, &pl, &pr);
if(op == 0) {
add(1, 1, n);
} else {
px = 0;
ft(1, 1, n);
pp("%d\n", px);
}
}
}