結果
| 問題 |
No.2443 特殊線形群の標準表現
|
| コンテスト | |
| ユーザー |
MasKoaTS
|
| 提出日時 | 2023-08-10 15:12:37 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 1,671 ms / 3,000 ms |
| コード長 | 3,433 bytes |
| コンパイル時間 | 269 ms |
| コンパイル使用メモリ | 82,048 KB |
| 実行使用メモリ | 156,928 KB |
| 最終ジャッジ日時 | 2024-11-16 21:52:01 |
| 合計ジャッジ時間 | 12,069 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 21 |
ソースコード
# 入力の高速化なし
""" SegmentTree
ref : https://algo-logic.info/segment-tree/
"""
def segfunc(B, A):
ret = [[0, 0], [0, 0]]
for i in range(2):
for j in range(2):
for k in range(2):
ret[i][j] += A[i][k] * B[k][j]
ret[i][j] %= b
return ret
""" 単位元一覧
min: INF
max: -INF
XOR: 0
区間和: 0
区間積: 1
GCD: 0
"""
ide_ele = [[1, 0], [0, 1]]
class SegmentTree:
""" セグメント木(非可換な演算を考慮)
セグ木に乗せる代数的構造はモノイドである必要がある。すなわち、
・結合律 : 任意のa,b,cに対して (a * b) * c = a * (b * c) が成り立つ
・単位元の存在 : あるeが存在し、任意のxに対して e * x = x * e = e である
を満たさなければならない。
init(init_val, ide_ele): 単位元をide_eleとして配列init_valで初期化 O(N)
update(k, x): k番目の値をxに更新 O(logN)
query(l, r): 区間[l, r)をsegfuncしたものを返す O(logN)
"""
def __init__(self, init_val, segfunc, ide_ele):
""" コンストラクタ
init_val: 配列の初期値
segfunc: 区間で作用させる演算
ide_ele: 単位元
n: 要素数
num: n以上の最小の2のべき乗
tree: セグメント木(1-based)
"""
n = len(init_val)
self.segfunc = segfunc
self.ide_ele = ide_ele
self.num = 1 << (n - 1).bit_length()
self.tree = [ide_ele] * (self.num << 1)
# 配列の値を葉にセット
for i in range(n):
self.tree[self.num + i] = init_val[i]
# 完全二分木を構築
for i in range(self.num - 1, 0, -1):
self.tree[i] = self.segfunc(self.tree[i << 1], self.tree[(i << 1) | 1])
def update(self, k, x):
""" k番目の値をxに更新
k: 更新位置(0-based)
x: 更新値
"""
k += self.num
self.tree[k] = x
while(k > 1):
self.tree[k >> 1] = self.segfunc(self.tree[k ^ (k & 1)], self.tree[k ^ ~(k & 1)])
k >>= 1
def query(self, l, r):
""" [l, r)についてsegfuncしたものを得る
l: 区間左端(0-based)
r: 区間右端(0-based); r自身は含まない
"""
ret = self.ide_ele
l += self.num
r += self.num
left_trees = []
right_trees = []
while(l < r):
if(l & 1):
left_trees.append(self.tree[l])
l += 1
if(r & 1):
right_trees.append(self.tree[r - 1])
l >>= 1
r >>= 1
left_trees.reverse()
while(left_trees):
ret = self.segfunc(ret, left_trees.pop())
while(right_trees):
ret = self.segfunc(ret, right_trees.pop())
return ret
"""
Main Code
"""
n, b, q = map(int, input().split())
As = [[list(map(int, input().split())) for _ in [0] * 2] for _ in [0] * n]
query = [list(map(int, input().split())) for _ in [0] * q]
seg = SegmentTree(As, segfunc, ide_ele)
def prod_vector(A, vec):
ret = [0, 0]
for i in range(2):
for j in range(2):
ret[i] += A[i][j] * vec[j]
ret[i] %= b
return ret
for l, r, x, y in query:
vec = [x, y]
ans = prod_vector(seg.query(l, r), vec)
print(*ans)
MasKoaTS