#include <cmath> #include <cstdio> #include <cstring> #include <iostream> using namespace std;
typedef long long ll; const int N = 5e5+15;
struct type { int cnt[10]; ll mul; type() { memset(cnt, 0, sizeof(cnt)); mul = 1; } };
namespace tree { struct node { int l, r; ll sum; type lz; } a[N*4]; ll val[N]; void build(int l, int r, int i = 1); void modify(int ql, int qr, type &tmp, int i = 1); void div(int pos, type &tmp, int i = 1); ll query(int ql, int qr ,int i = 1); } using namespace tree;
int n, P, q; int data[N]; int p[10], tot; int pow_v[10][N*20];
void divide(); void prework_pow(); ll get_pow(int i, int j);
signed main() { cin >> n >> P; for(int i = 1; i <= n; i++) cin >> data[i]; divide(); prework_pow(); tree::build(1, n); cin >> q; int opt, l, r, x; for(int i = 1; i <= q; i++) { cin >> opt; if(opt == 1) { cin >> l >> r >> x; type tmp; for(int j = 1; j <= tot; j++) while(x%p[j] == 0) x /= p[j], tmp.cnt[j]++; tmp.mul = x; tree::modify(l, r, tmp); } else if(opt == 2) { cin >> l >> x; type tmp; for(int j = 1; j <= tot; j++) while(x%p[j] == 0) x /= p[j], tmp.cnt[j]++; tmp.mul = x; tree::div(l, tmp); } else if(opt == 3) { cin >> l >> r; cout << tree::query(l, r) << "\n"; } } }
void divide() { int tmp = P; for(int i = 2; (ll)i*i <= tmp; i++) { if(tmp%i == 0) { p[++tot] = i; while(tmp%i == 0) tmp /= i; } } if(tmp != 1) p[++tot] = tmp; } void prework_pow() { for(int i = 1; i <= tot; i++) { pow_v[i][0] = 1; for(int j = 1; j < N*20; j++) pow_v[i][j] = (ll)pow_v[i][j-1]*p[i]%P; } } ll get_pow(int i, int j) {
return pow_v[i][j]; }
namespace tree { #define ls (i<<1) #define rs (i<<1|1) ll exgcd(ll a, ll b, ll &x, ll &y) { if(!b) return x = 1, y = 0, b; ll d = exgcd(b, a%b, y, x); y -= (a/b)*x; return d; } ll inv(ll a, ll p) { ll x, y; exgcd(a, p, x, y); x = (x%p+p)%p; return x; } void modify(node &i, type &tmp) { (i.sum *= tmp.mul) %= P; (i.lz.mul *= tmp.mul) %= P; if(i.l == i.r) (val[i.l] *= tmp.mul) %= P; for(int j = 1; j <= tot; j++) { i.lz.cnt[j] += tmp.cnt[j]; (i.sum *= get_pow(j,tmp.cnt[j])) %= P; } } void push_up(int i) { a[i].sum = (a[ls].sum + a[rs].sum)%P; } void push_down(int i) { modify(a[ls], a[i].lz); modify(a[rs], a[i].lz); memset(a[i].lz.cnt, 0, sizeof(a[i].lz.cnt)); a[i].lz.mul = 1; } void build(int l, int r, int i) { a[i].l = l, a[i].r = r; if(l == r) { int x = data[l]; for(int j = 1; j <= tot; j++) { int cnt = 0; while(x%p[j] == 0) x /= p[j], cnt++; a[i].lz.cnt[j] = cnt; } val[l] = x; a[i].sum = data[l]%P; return void(); } int mid = (l+r)>>1; build(l, mid, ls); build(mid+1, r, rs); push_up(i); } void modify(int ql, int qr, type &tmp, int i) { if(ql <= a[i].l && a[i].r <= qr) return modify(a[i], tmp); push_down(i); if(ql <= a[ls].r) modify(ql, qr, tmp, ls); if(qr >= a[rs].l) modify(ql, qr, tmp, rs); push_up(i); } void div(int pos, type &tmp, int i) { if(a[i].l == a[i].r) { (val[a[i].l] *= inv(tmp.mul, P)) %= P; a[i].sum = val[a[i].l]; for(int j = 1; j <= tot; j++) { a[i].lz.cnt[j] -= tmp.cnt[j]; (a[i].sum *= get_pow(j,a[i].lz.cnt[j])) %= P; } return void(); } push_down(i); if(pos <= a[ls].r) div(pos, tmp, ls); if(pos >= a[rs].l) div(pos, tmp, rs); push_up(i); } ll query(int ql, int qr, int i) { if(ql <= a[i].l and a[i].r <= qr) return a[i].sum; push_down(i); ll ans = 0; if(ql <= a[ls].r) ans += query(ql, qr, ls); if(qr >= a[rs].l) ans += query(ql, qr, rs); return ans%P; } }
|