RE求调!
查看原帖
RE求调!
378467
Windy_YY楼主2023/4/26 22:51
#include <bits/stdc++.h>
#define int long long
using namespace std;
// ================== Matrix ==================
template<int Mod>
struct matrix
{
public:
  int n, m;
  int z[3][3];
  matrix()
  {
    n = m = 0;
    memset(z, 0, sizeof z);
  }
  void init(int x, int y)
  {
    n = x, m = y;
    for (int i = 1; i <= x; i++)
      for (int j = 1; j <= y; j++)
        z[i][j] = 0;
  }
  void init(int x, int y, int a[3][3])
  {
    n = x, m = y;
    for (int i = 1; i <= x; i++)
      for (int j = 1; j <= y; j++)
        z[i][j] = a[i][j];
  }
  void O()
  {
    n = m = 2;
    z[0][0] = z[1][1] = z[0][1] = z[1][0] = 0;
  }
  void I()
  {
    n = m = 2;
    z[0][0] = z[1][1] = 1;
    z[0][1] = z[1][0] = 0;
  }
  bool CICN()
  {
    return z[0][0] == 1 && z[1][1] == 1 && z[0][1] == 0 && z[1][0] == 0;
  }
};
template<int Mod>
istream &operator>>(istream &in, matrix<Mod> &x)
{
  in >> x.n >> x.m;
  for (int i = 1; i <= x.n; i++)
    for (int j = 1; j <= x.m; j++)
      in >> x.z[i][j];
  return in;
}
template<int Mod>
ostream &operator<<(ostream &out, matrix<Mod> &x)
{
  for (int i = 1; i <= x.n; i++, cout << '\n')
    for (int j = 1; j <= x.m; j++)
      out << x.z[i][j] << ' ';
  return out;
}
template<int Mod>
matrix<Mod> operator+(const matrix<Mod> &a, const matrix<Mod> &b)
{
  assert(a.n == b.n && a.m == b.m);
  matrix<Mod> c;
  c.n = a.n, c.m = a.m;
  for (int i = 1; i <= c.n; i++)
    for (int j = 1; j <= c.m; j++)
      c.z[i][j] = a.z[i][j] + b.z[i][j];
  return c;
}
template<int Mod>
matrix<Mod> operator*(const matrix<Mod> &a, const matrix<Mod> &b)
{
  assert(a.m == b.n);
  matrix<Mod> c;
  c.n = a.n, c.m = b.m;
  for (int i = 1; i <= c.n; i++)
    for (int k = 1; k <= a.m; k++)
      for (int j = 1; j <= c.m; j++)
        (c.z[i][j] += a.z[i][k] * b.z[k][j] % Mod) %= Mod;
  return c;
}
template<int Mod>
matrix<Mod> operator^(matrix<Mod> &a, int k)
{
  matrix<Mod> b; b.I();
  while (k)
  {
    if (k & 1)
      b = b * a;
    a = a * a;
    k /= 2;
  }
  return b;
}
// ================= Segment Tree =================
const int N = 2e5 + 10;
int a[N];
struct Node
{
  int l, r;
  matrix<1000000007> sum, tag;
  Node ()
  {
    l = r = 0;
    sum.init(0, 0), tag.init(0, 0);
  }
  void init(int p)
  {
    l = r = p;
    if (a[p] == 1)
      sum.z[0][0] = 1;
    else
    {
      sum.z[0][0] = sum.z[0][1] = 1;
      sum = sum ^ (a[p] - 2);
    }
  }
  void color(matrix<1000000007> p)
  {
    sum = sum * p;
    tag = tag * p;
  }
} z[N << 2];
Node operator+(const Node &lhs, const Node &rhs)
{
  Node res;
  res.l = lhs.l, res.r = rhs.r;
  res.sum = lhs.sum + rhs.sum;
  res.tag.I();
  return res;
}
void build(int l, int r, int rt)
{
  if (l == r)
    z[rt].init(l);
  else
  {
    int mid = l + r >> 1;
    build(l, mid, rt << 1);
    build(mid + 1, r, rt << 1 | 1);
    z[rt] = z[rt << 1] + z[rt << 1 | 1];
  }
}
void push_down(int rt)
{
  if (z[rt].tag.CICN())
  {
    z[rt << 1].color(z[rt].tag);
    z[rt << 1 | 1].color(z[rt].tag);
    z[rt].tag.I();
  }
}
void modify(int l, int r, int rt, int nowl, int nowr, matrix<1000000007> val)
{
  if (nowl <= l && r <= nowr)
    z[rt].color(val);
  else
  {
    int mid = l + r >> 1;
    push_down(rt);
    if (nowl <= mid)
      modify(l, mid, rt << 1, nowl, nowr, val);
    if (mid < nowr)
      modify(mid + 1, r, rt << 1 | 1, nowl, nowr, val);
    z[rt] = z[rt << 1] + z[rt << 1 | 1];
  }
}
int query(int l, int r, int rt, int nowl, int nowr)
{
  if (nowl <= l && r <= nowr)
    return z[rt].sum.z[0][0];
  int mid = l + r >> 1, sum = 0;
  push_down(rt);
  if (nowl <= mid)
    sum = query(l, mid, rt << 1, nowl, nowr);
  if (mid < nowr)
    sum += query(mid + 1, r, rt << 1 | 1, nowl, nowr);
  return sum;
}
signed main()
{
  int n, m;
  cin >> n >> m;
  for (int i = 1; i <= n; i++)
    cin >> a[i];
  build(1, n, 1);
  while (m--)
  {
    int o;
    cin >> o;
    if (o == 1)
    {
      int l, r, x;
      cin >> l >> r >> x;
      matrix<1000000007> t; t.I();
      modify(1, n, 1, l, r, t ^ x);
    }
    else
    {
      int l, r;
      cin >> l >> r;
      cout << query(1, n, 1, l, r) << '\n';
    }
  }
  return 0;
}

2023/4/26 22:51
加载中...