什么把模数因数分解+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];
			}
		}
}
posted @ 2024-10-12 19:21  ccxswl  阅读(11)  评论(0编辑  收藏  举报