#include <bits/stdc++.h>
using
namespace
std;
#define ll long long int
#define MOD 1000000007
#define MAXN 1000001
int
spf[MAXN];
void
merge(
vector<pair<
int
,
int
> > tree[],
int
treeIndex);
void
sieve();
vector<
int
> getFactorization(
int
x);
void
buildTree(
vector<pair<
int
,
int
> > tree[],
int
treeIndex,
int
start,
int
end,
int
arr[]);
int
query(
vector<pair<
int
,
int
> > tree[],
int
treeIndex,
int
start,
int
end,
int
left,
int
right);
vector<pair<
int
,
int
> > mergeUtil(
vector<pair<
int
,
int
> > op1,
vector<pair<
int
,
int
> > op2);
vector<pair<
int
,
int
> > queryUtil(
vector<pair<
int
,
int
> > tree[],
int
treeIndex,
int
start,
int
end,
int
left,
int
right);
void
sieve()
{
spf[1] = 1;
for
(
int
i = 2; i < MAXN; i++)
spf[i] = i;
for
(
int
i = 4; i < MAXN; i += 2)
spf[i] = 2;
for
(
int
i = 3; i * i < MAXN; i++) {
if
(spf[i] == i) {
for
(
int
j = i * i; j < MAXN; j += i)
if
(spf[j] == j)
spf[j] = i;
}
}
}
vector<
int
> getFactorization(
int
x)
{
vector<
int
> ret;
while
(x != 1) {
ret.push_back(spf[x]);
x = x / spf[x];
}
return
ret;
}
void
buildTree(vector<pair<
int
,
int
> > tree[],
int
treeIndex,
int
start,
int
end,
int
arr[])
{
if
(start == end) {
int
val = arr[start];
vector<
int
> primeFac
= getFactorization(val);
for
(
auto
it : primeFac) {
int
power = 0;
while
(val % it == 0) {
val = val / it;
power++;
}
tree[treeIndex]
.push_back({ it, power });
}
return
;
}
int
mid = (start + end) / 2;
buildTree(tree, 2 * treeIndex, start,
mid, arr);
buildTree(tree, 2 * treeIndex + 1,
mid + 1, end, arr);
merge(tree, treeIndex);
return
;
}
void
merge(vector<pair<
int
,
int
> > tree[],
int
treeIndex)
{
int
index1 = 0;
int
index2 = 0;
int
len1 = tree[2 * treeIndex].size();
int
len2 = tree[2 * treeIndex + 1].size();
while
(index1 < len1 && index2 < len2) {
if
(tree[2 * treeIndex][index1].first
== tree[2 * treeIndex + 1][index2].first) {
tree[treeIndex].push_back(
{ tree[2 * treeIndex][index1].first,
tree[2 * treeIndex][index1].second
+ tree[2 * treeIndex + 1]
[index2]
.second });
index1++;
index2++;
}
else
if
(tree[2 * treeIndex][index1].first
> tree[2 * treeIndex + 1][index2].first) {
tree[treeIndex].push_back(
{ tree[2 * treeIndex + 1][index2].first,
tree[2 * treeIndex + 1][index2].second });
index2++;
}
else
{
tree[treeIndex].push_back(
{ tree[2 * treeIndex][index1].first,
tree[2 * treeIndex][index1].second });
index1++;
}
}
while
(index1 < len1) {
tree[treeIndex].push_back(
{ tree[2 * treeIndex][index1].first,
tree[2 * treeIndex][index1].second });
index1++;
}
while
(index2 < len2) {
tree[treeIndex].push_back(
{ tree[2 * treeIndex + 1][index2].first,
tree[2 * treeIndex + 1][index2].second });
index2++;
}
return
;
}
vector<pair<
int
,
int
> > mergeUtil(
vector<pair<
int
,
int
> > op1,
vector<pair<
int
,
int
> > op2)
{
int
index1 = 0;
int
index2 = 0;
int
len1 = op1.size();
int
len2 = op2.size();
vector<pair<
int
,
int
> > res;
while
(index1 < len1 && index2 < len2) {
if
(op1[index1].first == op2[index2].first) {
res.push_back({ op1[index1].first,
op1[index1].second
+ op2[index2].second });
index1++;
index2++;
}
else
if
(op1[index1].first > op2[index2].first) {
res.push_back({ op2[index2].first,
op2[index2].second });
index2++;
}
else
{
res.push_back({ op1[index1].first,
op1[index1].second });
index1++;
}
}
while
(index1 < len1) {
res.push_back({ op1[index1].first,
op1[index1].second });
index1++;
}
while
(index2 < len2) {
res.push_back({ op2[index2].first,
op2[index2].second });
index2++;
}
return
res;
}
vector<pair<
int
,
int
> > queryUtil(
vector<pair<
int
,
int
> > tree[],
int
treeIndex,
int
start,
int
end,
int
left,
int
right)
{
if
(start > right || end < left) {
tree[0].clear();
return
tree[0];
}
if
(start >= left && end <= right) {
return
tree[treeIndex];
}
int
mid = (start + end) / 2;
vector<pair<
int
,
int
> > op1
= queryUtil(tree, 2 * treeIndex,
start, mid,
left, right);
vector<pair<
int
,
int
> > op2
= queryUtil(tree, 2 * treeIndex + 1,
mid + 1, end,
left, right);
return
mergeUtil(op1, op2);
}
int
query(vector<pair<
int
,
int
> > tree[],
int
treeIndex,
int
start,
int
end,
int
left,
int
right)
{
vector<pair<
int
,
int
> > res
= queryUtil(tree, treeIndex,
start, end,
left, right);
int
sum = 1;
for
(
auto
it : res) {
sum *= (it.second + 1);
sum %= MOD;
}
return
sum;
}
void
solveQueries(
int
arr[],
int
len,
int
l,
int
r)
{
int
x = (
int
)(
ceil
(log2(len)));
int
max_size = 2 * (
int
)
pow
(2, x) - 1;
vector<pair<
int
,
int
> > tree[max_size];
buildTree(tree, 1, 0, len - 1, arr);
cout << query(tree, 1, 0,
len - 1, l - 1, r - 1)
<< endl;
}
int
main()
{
sieve();
int
arr[] = { 5, 2, 3, 1, 4 };
int
len =
sizeof
(arr) /
sizeof
(arr[0]);
int
queries = 2;
int
Q[queries][2] = { { 2, 4 }, { 1, 5 } };
for
(
int
i = 0; i < queries; i++) {
solveQueries(arr, len, Q[i][0], Q[i][1]);
}
return
0;
}