結果
問題 | No.426 往復漸化式 |
ユーザー |
![]() |
提出日時 | 2016-09-22 23:32:12 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 785 ms / 5,000 ms |
コード長 | 8,349 bytes |
コンパイル時間 | 2,111 ms |
コンパイル使用メモリ | 137,128 KB |
実行使用メモリ | 140,672 KB |
最終ジャッジ日時 | 2024-11-17 15:31:59 |
合計ジャッジ時間 | 13,380 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 1 |
other | AC * 22 |
ソースコード
#include <iostream>#include <cstdio>#include <cassert>#include <cstring>#include <vector>#include <valarray>#include <array>#include <queue>#include <set>#include <unordered_set>#include <map>#include <unordered_map>#include <algorithm>#include <cmath>#include <complex>#include <random>using namespace std;using uint = unsigned int;using ll = long long;using ull = unsigned long long;template<class T = ll> constexpr T TEN(int n) {return (n==0)?1:10*TEN<T>(n-1);}int bsr(int x) { return 31 - __builtin_clz(x); }/*** 行列ライブラリ*/template<class D>struct Matrix {vector<vector<D>> d;int N, M;Matrix(int N, int M) : N(N), M(M) {d.resize(N);for (int i = 0; i < N; i++) {d[i] = vector<D>(M);}}static Matrix One(int N) {Matrix r(N, N);for (int i = 0; i < N; i++) {r.d[i][i] = D(1);}return r;}vector<D>& operator[](int p) {return d[p];}const vector<D>& operator[](int p) const {return d[p];}const Matrix operator+(const Matrix &right) const {assert(right.N == N && right.M == M);Matrix res(N, M);for (int i = 0; i < N; i++) {for (int j = 0; j < M; j++) {res[i][j] = d[i][j]+right[i][j];}}return res;}const Matrix operator*(const Matrix &right) const {assert(M == right.N);Matrix res(N, right.M), r(right.M, right.N);for (int i = 0; i < right.M; i++) {for (int j = 0; j < right.N; j++) {r[i][j] = right[j][i];}}for (int i = 0; i < N; i++) {for (int j = 0; j < right.M; j++) {for (int k = 0; k < M; k++) {res[i][j] += d[i][k]*r[j][k];}}}return res;}const Matrix operator*(const D &x) const {Matrix res(N, M);for (int i = 0; i < N; i++) {for (int j = 0; j < M; j++) {res[i][j] = d[i][j]*x;}}return res;}};template<class T>Matrix<T> pow(Matrix<T> x, ll p) {assert(x.N == x.M);int N = x.N;Matrix<T> res(N, N), buf = x;for (int i = 0; i < N; i++) res[i][i] = T(1);while(p != 0) {if (p % 2) {res = res*buf;}p /= 2;buf = buf*buf;}return res;}template<uint MD>struct ModInt {uint v;ModInt() : v{0} {}ModInt(ll v) : v{normS(v%MD+MD)} {}static uint normS(const uint &x) {return (x<MD)?x:x-MD;};static ModInt make(const uint &x) {ModInt m; m.v = x; return m;}ModInt operator+(const ModInt &r) const {return make(normS(v+r.v));}ModInt operator-(const ModInt &r) const {return make(normS(v+MD-r.v));}ModInt operator*(const ModInt &r) const {return make(ull(v)*r.v%MD);}ModInt& operator+=(const ModInt &r) {return *this=*this+r;}ModInt& operator-=(const ModInt &r) {return *this=*this-r;}ModInt& operator*=(const ModInt &r) {return *this=*this*r;}static ModInt inv(const ModInt &x) {return pow(ModInt(x), MD-2);}};using Mint = ModInt<TEN(9)+7>;template<class N>struct SegTree {int lg, sz;vector<N> n;SegTree(int sz) {lg = bsr(2*sz-1);sz = 1<<lg;this->sz = sz;n = vector<N>(2*sz);for (int i = 2*sz-1; i >= sz; i--) {n[i].init(i-sz);}for (int i = sz-1; i >= 1; i--) {n[i] = N(n[2*i], n[2*i+1]);}}template<class Q>Q single(int idx, Q q) {if (idx < 0 or sz <= idx) return q;idx += sz;for (int i = lg; i >= 1; i--) {int k = idx>>i;n[k].push(n[2*k], n[2*k+1]);}q += n[idx];if (q.update()) {for (int i = 1; i <= lg; i++) {int k = idx>>i;n[k].update(n[2*k], n[2*k+1]);}}return q;}template<class Q>void query(int a, int b, Q &q, int k, int sz) {if (a <= 0 and sz <= b) {q += n[k];return;}n[k].push(n[2*k], n[2*k+1]);if (a < sz/2) query(a, b, q, 2*k, sz/2);if (sz/2 < b) query(a-sz/2, b-sz/2, q, 2*k+1, sz/2);if (q.update()) n[k].update(n[2*k], n[2*k+1]);}template<class Q>Q query(int a, int b, Q q) {if (a < sz and 0 < b) query(a, b, q, 1, sz);return q;}};using M = Matrix<Mint>;struct NodeA {using N = NodeA;M da = M::One(3); // aM dab = M(2, 3), dbb = M::One(2);int id;void init() {}void init(int id) {this->id = id;for (int i = 0; i < 2; i++) {for (int j = 0; j < 3; j++) {dab[i][j] = 6*(id+1) + 3*i + j;}}}NodeA() { init(); }NodeA(N &l, N &r) { init(-1); update(l, r); }void update(const N &l, const N &r) {da = r.da * l.da;dab = l.dab + l.dbb * r.dab * l.da;dbb = l.dbb * r.dbb;}void push(N &l, N &r) {}// querystruct GetQuery {M da = M::One(3);M dab = M(2, 3);M dbb = M::One(2);static constexpr bool update() { return false; }void operator+=(N &r) {dab = dab + dbb * r.dab * da;dbb = dbb * r.dbb;da = r.da * da;}};struct SetAQuery {M da = M(3, 3);SetAQuery(M da) : da(da) {}static constexpr bool update() { return true; }void operator+=(N &n) {n.da = da;M dab(2, 3);for (int i = 0; i < 2; i++) {for (int j = 0; j < 3; j++) {dab[i][j] = 6*(n.id+1) + 3*i + j;}}n.dab = dab * da;}};struct SetBQuery {M db = M(2, 2);SetBQuery(M db) : db(db) {}static constexpr bool update() { return true; }void operator+=(N &n) {n.dbb = db;}};};int main() {int n;scanf("%d", &n);M fa(3, 1), fb(2, 1);for (int i = 0; i < 3; i++) {int a;scanf("%d", &a);fa[i][0] = a;}for (int i = 0; i < 2; i++) {int b;scanf("%d", &b);fb[i][0] = b;}SegTree<NodeA> segA(n);int q;scanf("%d", &q);for (int qc = 0; qc < q; qc++) {char buf[3];scanf(" %s", buf);string s = buf;if (s == "a") {int id;scanf("%d", &id);M na(3, 3);for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {int a;scanf("%d", &a);na[i][j] = a;}}segA.single(id, NodeA::SetAQuery(na));} else if (s == "b") {int id;scanf("%d", &id); id--;M nb(2, 2);for (int i = 0; i < 2; i++) {for (int j = 0; j < 2; j++) {int a;scanf("%d", &a);nb[i][j] = a;}}segA.single(id, NodeA::SetBQuery(nb));} else if (s == "ga") {int id;scanf("%d", &id);auto res = segA.query(0, id, NodeA::GetQuery()).da * fa;for (int i = 0; i < 3; i++) {printf("%d", res[i][0].v);if (i < 3-1) {printf(" ");} else {printf("\n");}}fflush(stdout);} else if (s == "gb") {int id;scanf("%d", &id);auto aa = segA.query(0, id, NodeA::GetQuery()).da * fa;auto q = segA.query(id, n, NodeA::GetQuery());auto res = q.dab * aa + q.dbb * fb;for (int i = 0; i < 2; i++) {printf("%d", res[i][0].v);if (i < 2-1) {printf(" ");} else {printf("\n");}}fflush(stdout);}}return 0;}