結果
| 問題 |
No.426 往復漸化式
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2016-10-05 05:45:02 |
| 言語 | C++11(廃止可能性あり) (gcc 13.3.0) |
| 結果 |
AC
|
| 実行時間 | 71 ms / 5,000 ms |
| コード長 | 3,427 bytes |
| コンパイル時間 | 1,614 ms |
| コンパイル使用メモリ | 164,856 KB |
| 実行使用メモリ | 23,160 KB |
| 最終ジャッジ日時 | 2024-11-21 17:10:06 |
| 合計ジャッジ時間 | 3,169 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 22 |
コンパイルメッセージ
main.cpp: In function ‘int in()’:
main.cpp:126:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
126 | scanf("%d", &a);
| ~~~~~^~~~~~~~~~
main.cpp: In function ‘int main()’:
main.cpp:151:22: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
151 | scanf("%s", str);
| ~~~~~^~~~~~~~~~~
ソースコード
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
uint32_t inv;
int r2;
int one;
int reduce(uint64_t x) {
uint64_t y = uint64_t(uint32_t(x) * inv) * mod;
return int(x >> 32) + mod - int(y >> 32);
}
int transform(int n) {
return reduce(int64_t(n) * r2);
}
int normalize(int n) {
return n >= mod ? n - mod : n;
}
void init_montgomery_reduction() {
inv = 1;
for (int i = 0; i < 5; ++i) inv *= 2 - inv * uint32_t(mod);
r2 = -uint64_t(mod) % mod;
one = transform(1);
}
int modadd(int a, int b) {
return (a += b - mod) < 0 ? a + mod : a;
}
template<int H, int W>
struct Matrix {
int a[H][W] = {};
static Matrix I() {
Matrix<H, W> res;
for (int i = 0; i < H; i++) res[i][i] = one;
return res;
}
Matrix operator+(const Matrix<H, W> &b) const {
Matrix<H, W> s;
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
s.a[i][j] = modadd(a[i][j], b.a[i][j]);
}
}
return s;
}
template<int N>
Matrix<H, N> operator*(const Matrix<W, N> &b) const {
Matrix<H, N> s;
for (int i = 0; i < H; i++) {
for (int k = 0; k < W; k++) {
for (int j = 0; j < N; j++) {
s[i][j] = modadd(s[i][j], reduce(int64_t(a[i][k]) * b.a[k][j]));
}
}
}
return s;
}
int *operator[](int i) {
return a[i];
}
};
const int N = 1 << 17;
struct Tuple {
Matrix<3, 3> A;
Matrix<2, 2> B;
Matrix<2, 3> S;
Tuple() {
A = Matrix<3, 3>::I();
B = Matrix<2, 2>::I();
}
Tuple(Matrix<3, 3> A, Matrix<2, 2> B, Matrix<2, 3> S) : A(A), B(B), S(S) {}
Tuple operator*(const Tuple &r) const {
return Tuple(r.A * A, B * r.B, S + B * r.S * A);
}
};
Tuple seg[N * 2];
void build() {
for (int k = 0; k < N; k++) {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
seg[k + N].S[i][j] = transform(k * 6 + i * 3 + j);
}
}
for (int i = 0; i < 3; i++) seg[k + N].A[i][i] = one;
for (int i = 0; i < 2; i++) seg[k + N].B[i][i] = one;
}
for (int k = N - 1; k > 0; k--) {
seg[k] = seg[k * 2 + 0] * seg[k * 2 + 1];
}
}
void update(int k) {
k += N;
while (k > 1) {
k >>= 1;
seg[k] = seg[k * 2 + 0] * seg[k * 2 + 1];
}
}
Tuple query(int l, int r) {
Tuple L, R;
for (l += N, r += N; l < r; l >>= 1, r >>= 1) {
if (l & 1) L = L * seg[l++];
if (r & 1) R = seg[--r] * R;
}
return L * R;
}
int in() {
int a;
scanf("%d", &a);
return a;
}
int in_t() {
return transform(in());
}
int main() {
init_montgomery_reduction();
int n = in();
Matrix<3, 1> va;
Matrix<2, 1> vb;
for (int i = 0; i < 3; i++) va[i][0] = in_t();
for (int i = 0; i < 2; i++) vb[i][0] = in_t();
build();
int q = in();
for (int ii = 0; ii < q; ii++) {
char str[16];
scanf("%s", str);
if (str[0] == 'a') {
int k = in();
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) seg[k + N].A[i][j] = in_t();
}
update(k);
} else if (str[0] == 'b') {
int k = in();
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) seg[k + N].B[i][j] = in_t();
}
update(k);
} else if (str[1] == 'a') {
int k = in();
auto ans = query(0, k).A * va;
for (int i = 0; i < 3; i++) {
printf("%d ", normalize(reduce(ans[i][0])));
}
printf("\n");
} else if (str[1] == 'b') {
int k = in();
auto X = query(k + 1, n + 1);
auto Y = query(0, k + 1);
auto ans = X.B * vb + X.S * Y.A * va;
for (int i = 0; i < 2; i++) {
printf("%d ", normalize(reduce(ans[i][0])));
}
printf("\n");
}
}
}