1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
| #include <cstdio> #define int long long inline int min(const int x, const int y) {return x < y ? x : y;}
const int mod = 19940417; struct Node { int l, r, n, c[21], Lazy; bool rev; } tree[200005]; typedef int* Array; int a[50005], C[50005][21], n, q;
void pushup(int O) { for (int i = 1; i <= min(20, tree[O].n); ++ i) { tree[O].c[i] = tree[O << 1].c[i] + tree[O << 1 | 1].c[i]; for (int j = 1; j < i; ++ j) tree[O].c[i] = (tree[O].c[i] + tree[O << 1].c[j] * tree[O << 1 | 1].c[i - j]) % mod; } } void reverse(int O) { for (int i = 1; i <= min(20, tree[O].n); i += 2) tree[O].c[i] = -tree[O].c[i]; tree[O].Lazy = -tree[O].Lazy; } void add(int O, int d) { for (int i = min(20, tree[O].n); i; -- i) { int ret = 0; for (int j = 1, x = d; j <= i; ++ j, x = x * d % mod) ret = (ret + x * C[tree[O].n - i + j][j] % mod * tree[O].c[i - j]) % mod; tree[O].c[i] = (tree[O].c[i] + ret); } } void pushdown(int O) { if (tree[O].rev) { tree[O << 1].rev ^= 1, tree[O << 1 | 1].rev ^= 1; reverse(O << 1), reverse(O << 1 | 1); tree[O].rev = false; } if (tree[O].Lazy) { tree[O << 1].Lazy += tree[O].Lazy, tree[O << 1 | 1].Lazy += tree[O].Lazy; add(O << 1, tree[O].Lazy), add(O << 1 | 1, tree[O].Lazy); tree[O].Lazy = 0; } }
void make_tree(int O, int L, int R) { tree[O].l = L, tree[O].r = R, tree[O].n = R - L + 1, tree[O].c[0] = 1; if (L != R) { make_tree(O << 1, L, L + R >> 1); make_tree(O << 1 | 1, (L + R >> 1) + 1, R); pushup(O); } else tree[O].c[1] = a[L]; }
void update(int O, int L, int R, int d) { if (L <= tree[O].l && tree[O].r <= R) { add(O, d), tree[O].Lazy += d; return; } int mid = tree[O].l + tree[O].r >> 1; pushdown(O); if (L <= mid) update(O << 1, L, R, d); if (mid < R) update(O << 1 | 1, L, R, d); pushup(O); } void Reverse(int O, int L, int R) { if (L <= tree[O].l && tree[O].r <= R) { reverse(O), tree[O].rev ^= 1; return; } int mid = tree[O].l + tree[O].r >> 1; pushdown(O); if (L <= mid) Reverse(O << 1, L, R); if (mid < R) Reverse(O << 1 | 1, L, R); pushup(O); } Array query(int O, int L, int R) { if (L <= tree[O].l && tree[O].r <= R) { int* c = new int[21]; for (int i = 0; i <= 20; ++ i) c[i] = 0; for (int i = 1; i <= min(20, tree[O].n); ++ i) c[i] = tree[O].c[i]; return c; } pushdown(O); int mid = tree[O].l + tree[O].r >> 1; if (mid >= R) return query(O << 1, L, R); if (L > mid) return query(O << 1 | 1, L, R); int *a = query(O << 1, L, R), *b = query(O << 1 | 1, L, R), *c = new int[21]; for (int i = 0; i <= 20; ++ i) c[i] = 0; for (int i = 1; i <= min(20, tree[O].n); ++ i) { c[i] = a[i] + b[i]; for (int j = 1; j < i; ++ j) c[i] = (c[i] + a[j] * b[i - j] % mod) % mod; } delete a, delete b; return c; }
signed main() { scanf("%lld%lld", &n, &q); C[0][0] = 1; for (int i = 1; i <= n; ++ i) { scanf("%lld", a + i); C[i][0] = 1; for (int j = 1; j <= min(i, 20); ++ j) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod; } make_tree(1, 1, n); while (q --) { char opt; int l, r, v; scanf(" %c%lld%lld", &opt, &l, &r); if (opt == 'I') scanf("%lld", &v), update(1, l, r, v); else if (opt == 'R') Reverse(1, l, r); else scanf("%lld", &v), printf("%lld\n", (query(1, l, r)[v] + mod) % mod); } }
|