Codeforces 1109E Sasha and a Very Easy Test 线段树
因为mod不是质数, 所以要处理一下除的操作, 考虑吧mod分解质因数, 然后把所有数都按mod
分解出来的质因数进行拆分, 然后就能维护了。
#include<bits/stdc++.h> #define LL long long using namespace std; const int N = (int)1e5 + 7; int mod; struct Bit { int a[N]; inline void modify(int x, int v) { for(int i = x; i < N; i += i & -i) { a[i] += v; } } int sum(int x) { int ans = 0; for(int i = x; i; i -= i & -i) { ans += a[i]; } return ans; } }; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 struct SegmentTree { int sum[N << 2]; int lazy[N << 2]; inline void pull(int rt) { sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; if(sum[rt] >= mod) sum[rt] -= mod; } inline void push(int rt) { if(lazy[rt] != 1) { sum[rt << 1] = 1LL * sum[rt << 1] * lazy[rt] % mod; sum[rt << 1 | 1] = 1LL * sum[rt << 1 | 1] * lazy[rt] % mod; lazy[rt << 1] = 1LL * lazy[rt << 1] * lazy[rt] % mod; lazy[rt << 1 | 1] = 1LL * lazy[rt << 1 | 1] * lazy[rt] % mod; lazy[rt] = 1; } } void build(int l, int r, int rt) { lazy[rt] = 1; if(l == r) { sum[rt] = 1; return; } int mid = l + r >> 1; build(lson); build(rson); pull(rt); } void update(int L, int R, int val, int l, int r, int rt) { if(R < l || r < L || R < L) return; if(L <= l && r <= R) { sum[rt] = 1LL * sum[rt] * val % mod; lazy[rt] = 1LL * lazy[rt] * val % mod; return; } push(rt); int mid = l + r >> 1; update(L, R, val, lson); update(L, R, val, rson); pull(rt); } void update2(int p, int val, int l, int r, int rt) { if(l == r) { sum[rt] = val; return; } push(rt); int mid = l + r >> 1; if(p <= mid) update2(p, val, lson); else update2(p, val, rson); pull(rt); } int query(int L, int R, int l, int r, int rt) { if(R < l || r < L || R < L) return 0; if(L <= l && r <= R) return sum[rt]; push(rt); int mid = l + r >> 1; return (query(L, R, lson) + query(L, R, rson)) % mod; } }; int n, q, a[N]; SegmentTree real_val, inv_val; Bit bit[10]; int mul_val[N]; vector<int> F, C; vector<int> V[N]; int power(int a, int b) { int ans = 1; while(b) { if(b & 1) ans = 1LL * ans * a % mod; a = 1LL * a * a % mod; b >>= 1; } return ans; } void mul_modify(int L, int R, int val) { if(val == 1) return; inv_val.update(L, R, mul_val[val], 1, n, 1); real_val.update(L, R, val, 1, n, 1); for(int i = 0; i < V[val].size(); i++) { if(!V[val][i]) continue; bit[i].modify(L, V[val][i]); bit[i].modify(R + 1, -V[val][i]); } } int ex_gcd(int a, int b, int &x, int &y) { if(b == 0) { x = 1; y = 0; return a; } int r = ex_gcd(b, a % b, x, y); int t = x; x = y; y = t - a / b * y; return r; } int inv(int a, int mod) { int d, x, y; d = ex_gcd(a, mod, x, y); if(d == 1) return (x % mod + mod) % mod; else assert(0); } void div_modify(int p, int val) { if(val == 1) return; for(int i = 0; i < V[val].size(); i++) { if(!V[val][i]) continue; bit[i].modify(p, -V[val][i]); bit[i].modify(p + 1, V[val][i]); } int gg = 1; for(int i = 0; i < F.size(); i++) { gg = 1LL * gg * power(F[i], bit[i].sum(p)) % mod; } int nex_inv = 1LL * inv_val.query(p, p, 1, n, 1) * inv(mul_val[val], mod) % mod; inv_val.update2(p, nex_inv, 1, n, 1); if(gg) real_val.update2(p, 1LL * nex_inv * gg % mod, 1, n, 1); } int query(int L, int R) { return real_val.query(L, R, 1, n, 1); } void show() { puts(""); for(int i = 1; i <= n; i++) { printf("%d ", real_val.query(i, i, 1, n, 1)); } puts(""); } int main() { scanf("%d%d", &n, &mod); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); real_val.build(1, n, 1); inv_val.build(1, n, 1); int tmp = mod; for(int i = 2; i * i <= tmp; i++) { if(tmp % i) continue; F.push_back(i); int cnt = 0; while(tmp % i == 0) { cnt++; tmp /= i; } C.push_back(cnt); } if(tmp > 1) F.push_back(tmp), C.push_back(1); for(int i = 2; i <= 100000; i++) { mul_val[i] = i; for(auto &t : F) { while(mul_val[i] % t == 0) { mul_val[i] /= t; } } } for(int i = 2; i <= 100000; i++) { for(int j = 0; j < F.size(); j++) { int cnt = 0, now = i; while(now % F[j] == 0) { cnt++; now /= F[j]; } V[i].push_back(cnt); } } for(int i = 1; i <= n; i++) { mul_modify(i, i, a[i]); } scanf("%d", &q); while(q--) { int op; scanf("%d", &op); if(op == 1) { int l, r, x; scanf("%d%d%d", &l, &r, &x); mul_modify(l, r, x); } else if(op == 2) { int p, x; scanf("%d%d", &p, &x); div_modify(p, x); } else { int l, r; scanf("%d%d", &l, &r); printf("%d\n", query(l, r)); } } return 0; } /* */