import
java.util.SortedSet;
import
java.util.TreeSet;
class
GFG {
private
static
final
int
MOD =
1000000000
;
private
static
final
int
MAX =
100
;
private
static
final
int
SZ =
40
;
private
static
int
[] BIT =
new
int
[MAX +
1
];
private
static
int
[] fact =
new
int
[SZ +
1
];
private
static
class
Queries {
public
int
type;
public
int
l;
public
int
r;
public
Queries(
int
type,
int
l,
int
r)
{
this
.type = type;
this
.l = l;
this
.r = r;
}
}
private
static
void
update(
int
x,
int
val,
int
n)
{
for
(; x <= n; x += x & -x) {
BIT[x] += val;
}
}
private
static
int
sum(
int
x)
{
int
s =
0
;
for
(; x >
0
; x -= x & -x) {
s += BIT[x];
}
return
s;
}
private
static
void
answerQueries(
int
[] arr, Queries[] que,
int
n,
int
q)
{
fact[
0
] =
1
;
for
(
int
i =
1
; i <
41
; i++) {
fact[i] = (fact[i -
1
] * i) % MOD;
}
SortedSet<Integer> s =
new
TreeSet<>();
for
(
int
i =
1
; i < n; i++) {
if
(arr[i] <
40
) {
s.add(i);
update(i, fact[arr[i]], n);
}
else
{
update(i,
0
, n);
}
}
for
(
int
i =
0
; i < q; i++) {
if
(que[i].type ==
1
) {
SortedSet<Integer> view
= s.subSet(que[i].l, que[i].r +
1
);
for
(
int
idx : view) {
int
val = arr[idx] +
1
;
update(idx, fact[val] - fact[arr[idx]],
n);
arr[idx] = val;
if
(arr[idx] >=
40
) {
s.remove(idx);
}
}
}
else
if
(que[i].type ==
2
) {
int
idx = que[i].l;
int
val = que[i].r;
update(idx, fact[val] - fact[arr[idx]], n);
arr[idx] = val;
if
(val <
40
) {
s.add(idx);
}
else
{
s.remove(idx);
}
}
else
{
System.out.println(sum(que[i].r)
- sum(que[i].l -
1
));
}
}
}
public
static
void
main(String[] args)
{
int
q =
6
;
int
[] arr = {
0
,
1
,
2
,
1
,
4
,
5
};
int
n = arr.length;
Queries[] que =
new
Queries[q +
1
];
que[
0
] =
new
Queries(
3
,
1
,
5
);
que[
1
] =
new
Queries(
1
,
1
,
3
);
que[
2
] =
new
Queries(
2
,
2
,
4
);
que[
3
] =
new
Queries(
3
,
2
,
4
);
que[
4
] =
new
Queries(
1
,
2
,
5
);
que[
5
] =
new
Queries(
3
,
1
,
5
);
answerQueries(arr, que, n, q);
}
}