結果

問題 No.510 二次漸化式
ユーザー tnakao0123tnakao0123
提出日時 2017-04-29 15:37:52
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 80 ms / 3,000 ms
コード長 3,672 bytes
コンパイル時間 1,245 ms
コンパイル使用メモリ 87,404 KB
実行使用メモリ 36,492 KB
最終ジャッジ日時 2024-09-13 22:51:25
合計ジャッジ時間 5,696 ms
ジャッジサーバーID
(参考情報)
judge2 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 12 ms
36,384 KB
testcase_01 AC 13 ms
36,324 KB
testcase_02 AC 47 ms
36,332 KB
testcase_03 AC 48 ms
36,372 KB
testcase_04 AC 48 ms
36,224 KB
testcase_05 AC 47 ms
36,252 KB
testcase_06 AC 63 ms
36,344 KB
testcase_07 AC 62 ms
36,368 KB
testcase_08 AC 62 ms
36,492 KB
testcase_09 AC 63 ms
36,356 KB
testcase_10 AC 27 ms
36,384 KB
testcase_11 AC 28 ms
36,348 KB
testcase_12 AC 28 ms
36,284 KB
testcase_13 AC 28 ms
36,240 KB
testcase_14 AC 28 ms
36,176 KB
testcase_15 AC 28 ms
36,464 KB
testcase_16 AC 45 ms
36,356 KB
testcase_17 AC 45 ms
36,424 KB
testcase_18 AC 45 ms
36,300 KB
testcase_19 AC 45 ms
36,332 KB
testcase_20 AC 45 ms
36,284 KB
testcase_21 AC 45 ms
36,424 KB
testcase_22 AC 46 ms
36,228 KB
testcase_23 AC 78 ms
36,392 KB
testcase_24 AC 78 ms
36,284 KB
testcase_25 AC 78 ms
36,264 KB
testcase_26 AC 78 ms
36,232 KB
testcase_27 AC 78 ms
36,412 KB
testcase_28 AC 78 ms
36,364 KB
testcase_29 AC 79 ms
36,176 KB
testcase_30 AC 78 ms
36,180 KB
testcase_31 AC 80 ms
36,228 KB
testcase_32 AC 80 ms
36,284 KB
testcase_33 AC 80 ms
36,384 KB
testcase_34 AC 71 ms
36,312 KB
testcase_35 AC 56 ms
36,256 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
main.cpp: In function ‘int main()’:
main.cpp:167:8: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  167 |   scanf("%d%d", &n, &qn);
      |   ~~~~~^~~~~~~~~~~~~~~~~
main.cpp:177:10: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  177 |     scanf("%c %d", &op, &i);
      |     ~~~~~^~~~~~~~~~~~~~~~~~
main.cpp:181:12: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  181 |       scanf("%d", &v);
      |       ~~~~~^~~~~~~~~~

ソースコード

diff #

/* -*- coding: utf-8 -*-
 *
 * 510.cc: No.510 二次漸化式 - yukicoder
 */

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<deque>
#include<algorithm>
#include<numeric>
#include<utility>
#include<complex>
#include<functional>
 
using namespace std;

/* constant */

const int MAX_N = 100000;
const int MAX_E2 = 1 << 18; // 262144
const int N = 4;

typedef long long ll;
const ll MOD = 1000000007;

/* typedef */

typedef vector<int> vi;
typedef queue<int> qi;
typedef pair<int,int> pii;

struct Vec {
  ll v[N];
  Vec(): v() {}
  Vec(const ll _v[N]) { memcpy(v, _v, sizeof(v)); }
};

const ll IDV0[] = {1, 1, 1, 1};
const Vec V0(IDV0);

struct Mat {
  ll m[N][N];
  Mat() {}
  Mat(const ll _m[N][N]) { memcpy(m, _m, sizeof(m)); }
  void init(const ll _m[N][N]) { memcpy(m, _m, sizeof(m)); }

  Mat operator*(const Mat &a) const {
    Mat r;
    for (int i = 0; i < N; i++)
      for (int j = 0; j < N; j++) {
	r.m[i][j] = 0;
	for (int k = 0; k < N; k++)
	  r.m[i][j] += m[i][k] * a.m[k][j] % MOD;
	r.m[i][j] %= MOD;
      }
    return r;
  }

  Vec operator*(const Vec &v) const {
    Vec r;
    for (int i = 0; i < N; i++) {
      r.v[i] = 0;
      for (int j = 0; j < N; j++)
	r.v[i] += m[i][j] * v.v[j] % MOD;
      r.v[i] %= MOD;
    }
    return r;
  }

  void print() {
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) printf("%lld ", m[i][j]);
      putchar('\n');
    }
  }
};

const ll ID[N][N] = {
  {1, 0, 0, 0},
  {0, 0, 0, 1},
  {0, 0, 0, 1},
  {0, 0, 0, 1}
};

Mat IDMAT(ID);

struct SegTreeMat {
  int n, e2;
  Mat nodes[MAX_E2];
  SegTreeMat() {}

  void init(int _n) {
    n = _n;
    for (e2 = 1; e2 < n; e2 <<= 1);
    fill(nodes, nodes + MAX_E2, IDMAT);
  }

  Mat get(int i) { return nodes[e2 - 1 + i]; }

  void setx(int i, ll x) {
    int j = e2 - 1 + i;
    nodes[j].m[0][2] = x;
    j = (j - 1) / 2;

    for (;;) {
      nodes[j] = nodes[j * 2 + 2] * nodes[j * 2 + 1];
      if (j == 0) break;
      j = (j - 1) / 2;
    }
  }

  void sety(int i, ll y) {
    int j = e2 - 1 + i;
    nodes[j].m[1][1] = y;
    nodes[j].m[2][1] = 2 * y % MOD;
    nodes[j].m[2][2] = y * y % MOD;
    j = (j - 1) / 2;

    for (;;) {
      nodes[j] = nodes[j * 2 + 2] * nodes[j * 2 + 1];
      if (j == 0) break;
      j = (j - 1) / 2;
    }
  }

  Mat mul_range(int r0, int r1, int k, int i0, int i1) {
    if (r1 <= i0 || i1 <= r0) return IDMAT;
    if (r0 <= i0 && i1 <= r1) return nodes[k];

    int im = (i0 + i1) / 2;
    Mat v0 = mul_range(r0, r1, k * 2 + 1, i0, im);
    Mat v1 = mul_range(r0, r1, k * 2 + 2, im, i1);

    return v1 * v0;
  }

  Mat mul_range(int r0, int r1) {
    return mul_range(r0, r1, 0, 0, e2);
  }
};

/* global variables */

SegTreeMat st;

/* subroutines */

/* main */

// a{i+1}    |1 0   xi   0| ai
// b{i+1}  = |0 yi  0    1| bi
// b{i+1}^2  |0 2yi yi^2 1| bi^2
// 1         |0 0   0    1| 1

int main() {
  int n, qn;
  scanf("%d%d", &n, &qn);
  //printf("n=%d, qn=%d\n", n, qn);

  st.init(n);

  while (qn--) {
    while (getchar() != '\n');

    char op;
    int i;
    scanf("%c %d", &op, &i);

    if (op == 'x' || op == 'y') {
      int v;
      scanf("%d", &v);
      //printf("%c %d %d\n", op, i, v);
      if (op == 'x') st.setx(i, v);
      else st.sety(i, v);
    }
    else {
      //printf("%c %d\n", op, i);
      Mat mi = st.mul_range(0, i);
      //printf("mi=\n"), mi.print();
      Vec vv = mi * V0;
      printf("%lld\n", vv.v[0]);
    }
  }

  //for (int i = 0; i < n; i++) printf("%d:\n", i), st.get(i).print();
  return 0;
}
0