什么把模数因数分解+crt
什么把模数因数分解+crt
之前没见过。
ans % m1 = x1
ans % m2 = x2
...
ans % mi = xi
#include <bits/stdc++.h>
using namespace std;
using ubt = long long;
int read() {
int s = 0, w = 1;
char c = getchar();
while (!isdigit(c)) {
if (c == '-')
w = -w;
c = getchar();
}
while (isdigit(c)) {
s = s * 10 + c - 48;
c = getchar();
}
return w * s;
}
void pr(int x) {
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
pr(x / 10);
putchar(x % 10 + 48);
}
#define end_ putchar('\n')
#define spc_ putchar(' ')
const int maxN = 2e5 + 7;
int a[maxN], cnt, m[maxN], r[maxN], ny[maxN];
char op[maxN];
int phi;
int getphi(int n) {
int ans = n;
for (int i = 2; 1ll * i * i <= n; i++)
if (n % i == 0) {
ans = ans / i * (i - 1);
cnt++;
m[cnt] = 1;
while (n % i == 0)
n /= i, m[cnt] *= i;
}
if (n > 1) {
cnt++;
m[cnt] = n;
ans = ans / n * (n - 1);
}
return ans;
}
void exgcd(int a, int b, int &x, int &y) {
if (!b) {
x = 1, y = 0;
} else {
int tx, ty;
exgcd(b, a % b, tx, ty);
x = ty;
y = tx - a / b * ty;
}
}
int ksm(int a, int b, const int mod) {
int res = 1;
while (b) {
if (b & 1)
res = 1ll * res * a % mod;
a = 1ll * a * a % mod;
b >>= 1;
}
return res;
}
int inv(int a, const int mod) {
int x, y;
exgcd(a, mod, x, y);
x = (x % mod + mod) % mod;
return x;
}
struct tree {
int l, r;
int v[10][30];
} t[maxN * 4];
#define ls (p << 1)
#define rs (p << 1 | 1)
void upd(int p) {
for (int i = 1; i <= cnt; i++)
for (int j = 0; j < m[i]; j++)
t[p].v[i][j] = t[rs].v[i][t[ls].v[i][j]];
}
void modi(int p, int pos) {
if (op[pos] == '+') {
for (int i = 1; i <= cnt; i++)
for (int j = 0; j < m[i]; j++)
t[p].v[i][j] = (j + a[pos]) % m[i];
}
if (op[pos] == '*') {
for (int i = 1; i <= cnt; i++)
for (int j = 0; j < m[i]; j++)
t[p].v[i][j] = j * a[pos] % m[i];
}
if (op[pos] == '^') {
for (int i = 1; i <= cnt; i++)
for (int j = 0; j < m[i]; j++)
t[p].v[i][j] = ksm(j, a[pos], m[i]);
}
}
void build(int L, int R, int p) {
t[p].l = L, t[p].r = R;
if (L == R)
modi(p, L);
else {
int mid = (L + R) >> 1;
build(L, mid, ls);
build(mid + 1, R, rs);
upd(p);
}
}
void cg(int K, int p) {
if (t[p].l == t[p].r) {
modi(p, K);
return;
}
int mid = (t[p].l + t[p].r) >> 1;
K <= mid ? cg(K, ls) : cg(K, rs);
upd(p);
}
int ask(int i, int x) {
// cerr << t[1].v[i][x] << '\n';
return t[1].v[i][x];
}
#undef ls
#undef rs
int n, Q, mod;
int crt(int x) {
int ans = 0;
for (int i = 1; i <= cnt; i++)
ans = (ans + (ny[i] * r[i] % mod) * ask(i, x % m[i]) % mod) % mod;
return ans;
}
signed main() {
// freopen("t4.in", "r", stdin);
// freopen("1.out", "w", stdout);
freopen("expr.in", "r", stdin);
freopen("expr.out", "w", stdout);
int OPT = read();
n = read(), Q = read(), mod = read();
for (int i = 1; i <= n; i++)
cin >> op[i] >> a[i];
if (OPT > 3) {
phi = getphi(mod);
for (int i = 1; i <= n; i++)
if (op[i] != '^')
a[i] %= mod;
else if (a[i])
a[i] = a[i] % phi + phi;
for (int i = 1; i <= cnt; i++)
r[i] = mod / m[i], ny[i] = inv(r[i], m[i]);
build(1, n, 1);
while (Q--) {
int o = read();
if (o == 1) {
int x = read();
pr(crt(x)), end_;
} else {
int pos = read();
cin >> op[pos] >> a[pos];
if (op[pos] != '^')
a[pos] %= mod;
else if (a[pos])
a[pos] = a[pos] % phi + phi;
cg(pos, 1);
}
}
} else
while (Q--) {
int o = read();
if (o == 1) {
int x = read();
for (int i = 1; i <= n; i++) {
if (op[i] == '+')
x = (1ll * x + a[i]) % mod;
if (op[i] == '*')
x = 1ll * x * a[i] % mod;
if (op[i] == '^')
x = ksm(x, a[i], mod);
}
cout << x << '\n';
} else {
int p = read();
cin >> op[p] >> a[p];
}
}
}