← Home
```go
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

const MOD int64 = 1000000007
const MAXN int = 100005

type Matrix [2][2]int64

type Node struct {
	back Matrix
	fwd  Matrix
	lazy bool
}

var tree [4*MAXN]Node

func mul(A, B Matrix) Matrix {
	var C Matrix
	for i := 0; i < 2; i++ {
		for j := 0; j < 2; j++ {
			for k := 0; k < 2; k++ {
				C[i][j] = (C[i][j] + A[i][k]*B[k][j]) % MOD
			}
		}
	}
	return C
}

func transpose(M Matrix) Matrix {
	var T Matrix
	T[0][0] = M[0][0]
	T[0][1] = M[1][0]
	T[1][0] = M[0][1]
	T[1][1] = M[1][1]
	return T
}

func applyMat(M Matrix, vec [2]int64) [2]int64 {
	var res [2]int64
	res[0] = (M[0][0]*vec[0] + M[0][1]*vec[1]) % MOD
	res[1] = (M[1][0]*vec[0] + M[1][1]*vec[1]) % MOD
	return res
}

func build(idx int, tl int, tr int, S string) {
	if tl == tr {
		var m Matrix
		if S[tl-1] == 'A' {
			m = Matrix{{1, 1}, {0, 1}}
		} else {
			m = Matrix{{1, 0}, {1, 1}}
		}
		tree[idx].back = m
		tree[idx].fwd = m
		tree[idx].lazy = false
		return
	}
	mid := (tl + tr) / 2
	build(2*idx, tl, mid, S)
	build(2*idx+1, mid+1, tr, S)
	tree[idx].back = mul(tree[2*idx+1].back, tree[2*idx].back)
	tree[idx].fwd = mul(tree[2*idx].fwd, tree[2*idx+1].fwd)
	tree[idx].lazy = false
}

func push(idx int, tl int, tr int) {
	if tree[idx].lazy {
		if tl != tr {
			temp := tree[2*idx].back
			tree[2*idx].back = transpose(tree[2*idx].fwd)
			tree[2*idx].fwd = transpose(temp)
			tree[2*idx].lazy = !tree[2*idx].lazy

			temp = tree[2*idx+1].back
			tree[2*idx+1].back = transpose(tree[2*idx+1].fwd)
			tree[2*idx+1].fwd = transpose(temp)
			tree[2*idx+1].lazy = !tree[2*idx+1].lazy
		}
		tree[idx].lazy = false
	}
}

func update(idx int, tl int, tr int, ql int, qr int) {
	push(idx, tl, tr)
	if ql > tr || qr < tl {
		return
	}
	if ql <= tl && tr <= qr {
		temp := tree[idx].back
		tree[idx].back = transpose(tree[idx].fwd)
		tree[idx].fwd = transpose(temp)
		if tl != tr {
			tree[idx].lazy = true
		}
		return
	}
	mid := (tl + tr) / 2
	update(2*idx, tl, mid, ql, qr)
	update(2*idx+1, mid+1, tr, ql, qr)
	tree[idx].back = mul(tree[2*idx+1].back, tree[2*idx].back)
	tree[idx].fwd = mul(tree[2*idx].fwd, tree[2*idx+1].fwd)
}

func query(idx int, tl int, tr int, ql int, qr int) Matrix {
	push(idx, tl, tr)
	if ql > tr || qr < tl {
		return Matrix{{1, 0}, {0, 1}}
	}
	if ql <= tl && tr <= qr {
		return tree[idx].back
	}
	mid := (tl + tr) / 2
	rightp := query(2*idx+1, mid+1, tr, ql, qr)
	leftp := query(2*idx, tl, mid, ql, qr)
	return mul(rightp, leftp)
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	var N, Q int
	fmt.Fscan(reader, &N, &Q)
	text, _ := reader.ReadString('\n')
	S := strings.TrimSpace(text)
	build(1, 1, N, S)
	for q := 0; q < Q; q++ {
		line, _ := reader.ReadString('\n')
		parts := strings.Fields(line)
		typ, _ := strconv.Atoi(parts[0])
		if typ == 1 {
			L, _ := strconv.Atoi(parts[1])
			R, _ := strconv.Atoi(parts[2])
			update(1, 1, N, L, R)
		} else {
			L, _ := strconv.Atoi(parts[1])
			R, _ := strconv.Atoi(parts[2])
			A, _ := strconv.ParseInt(parts[3], 10, 64)
			B, _ := strconv.ParseInt(parts[4], 10, 64)
			M := query(1, 1, N, L, R)
			vec := [2]int64{A % MOD, B % MOD}
			res := applyMat(M, vec)
			fmt.Println(res[0], res[1])
		}
	}
}
```