https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1964
强烈建议在阅读时动手设计一下算法流程。会有助于理解。
解决此题。必须知道下面 T(n) 的增张速度。
T(n)=maxk=1n(T(k−1)+T(n−k)+min(k,n−k+1))
上式子可以看作有一排石子。
合并编号 [1,k−1] 的石子。代价 T(k−1)
合并编号 [k,n−1] 的式子。代价 T(n−k)
把
[1,k−1]
和
[k,n−1]
以及第
n
个式子合并起来.
代价T(k−1)+T(n−k)+min(k,n−k+1)
显然。这相当于。石子较少的那一堆石子的贡献全部 +1
显然。一个石子只能对编号是它两倍的石子产生新的贡献。
所以:
T(n)=O(nlog2n)
对于区间的所有价值。考虑在笛卡尔树上进行计算。
某一节点以及以这个节点为根的子树组成一段区间。并且根节点是最大值(相同大小。按位置对比)
显然。直观的想法。就是在笛卡尔树上计算所有区间价值。
因为最棘手的部分即使区间的价值计算时 max 次方。
这样在笛卡尔树上计算 max 的大小是一样的。所以可以一次性统一处理。
记: m=⌊105−−−√⌋
会发现。如果
P>m
.那么意味着所有元素都最多只含有一个
P
那么意味着。我们只需要知道。上一次或者下一次这两个位置之间是否可以包含根节点。如果包含。最小范围是多少。便可以得到P 对当前区间的贡献了。
所以我们只需要预处理出来
P
上一次出现的位置。便可以搞定这部分计算。
对于这种思路。那么必然需要两个区间之间的合并。
那么我们枚举节点数量较少的那个区间。启发式的合并。
这个复杂度就是:
T(n)=maxk=1n(T(k−1)+T(n−k)+min(k,n−k+1))=O(nlog2n)
你会发现。我们只是枚举了一侧区间。这就产生了一个问题。
如果枚举的一次没有出现
P′
,但另一侧有
P′
那么这种方法。
P′
的贡献我们是算不出来的。
但因为我们枚举的一侧没有
P′
,这就是说。我们不管如何选择区间枚举一侧的端点。
P′
的贡献是一样的。
这句话说的有些笼统。考虑区间选择。
如果我们枚举一侧枚举到某一端点时。那么另一侧
P′
所有选择的贡献总和与端点无关。便可以通过快速幂计算。
那么问题是我们需要维护所有
P
的贡献。不单单只有P′
如果上面你想明的白了。那么贡献是一个什么样的形式就很清楚了。
显然。有两个方向不同的贡献。
我们记。向右延伸的贡献为
AR
对应的。向左延伸的贡献为
AL
我们在枚举的同时。剔除
AR
,
AL
中两侧都有的素数的贡献。因为这部分贡献已经计算过了。
我们维护
AR,AL
时,还需要知道整个区间内不同素数的乘积。这是因为计算时候只枚举一侧。所产生问题所必须做的事情。
至此。
P>m
这部分的贡献已经
OK
了
<script id="MathJax-Element-39" type="math/tex; mode=display"></script>
现在计算
P≤m
这部分的贡献。
这部分贡献。因为
P
的种数较少。所以可以单独计算。
对于每种P ,我们只需要考虑指数大小。取区间指数最大的那个数就好。
显然我们需要知道指数第一个大于它的数前后位置。
如果大小相同。按照位置对比。必须有一个大小关系。避免重复
依然考虑枚举数量较小的那一测。
这意味着我们需要不断的查询某一侧的总体贡献。
我们预处理出来前后指数大于它的元素位置。通过这个位置查询。
显然这样暴力是不行的。但是我们会发现。查询一次可以把路径压缩了。
而路径压缩的耗费是可以 单独考虑的。
其与总路径数量是线性的。
显然:一个节点 最多链接两条边
那么。总路径数量是
O(n)
所以总的时间复杂度就是
O(nn√∗log2nlogen+nlog22n),题中。最大值和最大元素数量可以同时为n
由于所给空间比较小。强烈建议
BFS
。
DFS
过程可能会保存过多无用变量。递归深度过深。所以笛卡尔树建树时一定要存储区间范围。
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <cmath>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const int mod_1 = mod - 1;
const int MAXN = 100003;
const int Sqr = (int)sqrt(MAXN) + 1;
struct Io
{
char A[MAXN * 4],*L,*R;
int count;
Io()
{
L = R = A;
count = MAXN * 4;
}
void Io_fread()
{
L = A;
R = A + fread(A, sizeof(char), count, stdin);
}
int read()
{
int tmp = 0;
if (L == R)
{
Io_fread();
if (L == R)return 0;
}
while (*L<'0'||*L>'9')
{
L++;
if (L == R)
{
Io_fread();
if (L == R)return 0;
}
}
while (*L >= '0'&&*L <= '9')
{
tmp = tmp * 10 + (*L - '0');
L++;
if (L == R)
{
Io_fread();
if (L == R)return tmp;
}
}
return tmp;
}
}I;
int used[MAXN];
int buf[MAXN];
int G[MAXN];
int tmp[MAXN];
int tmp2[MAXN];
int nxt[MAXN];
int fst[MAXN];
int bnxt[MAXN];
int bfst[MAXN];
int queue[MAXN];
int stk[MAXN];
int *wnxt = tmp, *wfst = tmp2, *AL = tmp, *AR = tmp2, *C = used;
int ans = 1;
struct node
{
int c[2];
int L, R;
node()
{
L = R = c[0] = c[1] = 0;
}
};
struct Decare
{
node A[MAXN];
int root;
int deep;
Decare()
{
root = 0;
deep = 1;
}
void _insert(int key, int inof)
{
if (inof == 0)
{
root = deep++;
tmp[root] = key;
return;
}
while (inof)
{
if (tmp[inof] >= key)
{
tmp[deep] = key;
G[deep] = inof;
A[deep].c[0] = A[inof].c[1];
A[inof].c[1] = deep;
G[A[deep].c[0]] = deep;
deep++;
return;
}
inof = G[inof];
}
tmp[deep] = key;
A[deep].c[0] = root;
G[root] = deep;
root = deep++;
}
void insert(int key)
{
_insert(key, deep - 1);
}
void BFS(int root)
{
memset(tmp, 0, sizeof tmp);
int l = 0, r = 1;
stk[0] = root;
while (l < r)
{
int v = stk[l++];
if (A[v].c[0]) stk[r++] = A[v].c[0];
if (A[v].c[1]) stk[r++] = A[v].c[1];
}
int n = r;
while (r--)
{
int v = stk[r];
tmp[v] ++;
tmp[G[v]] += tmp[v];
}
tmp[0] = 0;
l = 0; r = 1;
A[root].L = 1;
A[root].R = n;
A[0].L = 1;
A[0].R = 0;
while (l<r)
{
int v = stk[l++];
A[A[v].c[0]].L = A[v].L;
A[A[v].c[0]].R = A[A[v].c[0]].L + tmp[A[v].c[0]] - 1;
A[A[v].c[1]].L = A[A[v].c[0]].R + 2;
A[A[v].c[1]].R = A[A[v].c[1]].L + tmp[A[v].c[1]] - 1;
if (A[v].c[0]) stk[r++] = A[v].c[0];
if (A[v].c[1]) stk[r++] = A[v].c[1];
}
memset(tmp, 0, sizeof tmp);
memset(G, 0, sizeof G);
A[0].L = 1;
A[0].R = 0;
}
}D;
int Pow(int a, int b)
{
int tmp = 1;
while (b)
{
if (b & 1)
tmp = (LL)tmp*a%mod;
a = (LL)a*a%mod;
b >>= 1;
}
return tmp;
}
int A[MAXN];
int find_nxt(int k, int B)
{
int top = -1, d = k;
while (bnxt[d] <= B)
{
stk[++top] = d;
d = bnxt[d];
}
while (top>-1)
{
int x = stk[top--];
if (bnxt[x] == nxt[x])wnxt[x] = A[x] * (bnxt[x] - x);
wnxt[x] += wnxt[bnxt[x]];
bnxt[x] = d;
}
return wnxt[k] + (B - d + 1)*A[d];
}
int find_fst(int k, int B)
{
int top = -1, d = k;
while (bfst[d] >= B)
{
stk[++top] = d;
d = bfst[d];
}
while (top>-1)
{
int x = stk[top--];
if (bfst[x] == fst[x]) wfst[x] = A[x] * (x - bfst[x]);
wfst[x] += wfst[bfst[x]];
bfst[x] = d;
}
return wfst[k] + (d - B + 1)*A[d];
}
void BFS_1(int root, int P)
{
int l = 0, r = 1;
queue[0] = root;
while (l < r)
{
int v = queue[l++];
if (D.A[v].c[0])queue[r++] = D.A[v].c[0];
if (D.A[v].c[1])queue[r++] = D.A[v].c[1];
}
while (r--)
{
int v = queue[r];
int *c = D.A[v].c;
int L = D.A[v].L;
int R = D.A[v].R;
if (L == R)
{
G[P] = (G[P] + (LL)A[L] * buf[L] % (mod_1)) % mod_1;
continue;
}
int mid = (c[0]) ? D.A[c[0]].R + 1 : D.A[c[1]].L - 1;
if ((D.A[c[0]].R - D.A[c[0]].L + 1)<(D.A[c[1]].R - D.A[c[1]].L + 1))
{
for (int i = mid; i >= L; i = fst[i])
{
if (nxt[i] <= R)
{
int bk = fst[i] < L ? L : fst[i] + 1;
G[P] += ((LL)(i - bk + 1)*(nxt[i] - mid) % (mod - 1))*((LL)A[i] * buf[mid] % (mod - 1)) % (mod - 1);
if (G[P] >= mod - 1)G[P] -= mod - 1;
G[P] += (LL)(i - bk + 1)*(buf[mid]) % (mod - 1)*find_nxt(nxt[i], R) % (mod - 1);
if (G[P] >= mod - 1)G[P] -= mod - 1;
}
else
{
int bk = fst[i]<L ? L : fst[i] + 1;
G[P] += ((LL)(i - bk + 1)*(R - mid + 1) % (mod - 1))*((LL)A[i] * buf[mid] % (mod - 1)) % (mod - 1);
if (G[P] >= mod - 1)G[P] -= mod - 1;
}
}
}
else
{
for (int i = mid; i <= R; i = nxt[i])
{
if (fst[i] >= L)
{
int bk = nxt[i]>R ? R : nxt[i] - 1;
G[P] += ((LL)(bk - i + 1)*(mid - fst[i]) % (mod - 1))*((LL)A[i] * buf[mid] % (mod - 1)) % (mod - 1);
if (G[P] >= mod - 1)G[P] -= mod - 1;;
G[P] += (LL)(bk - i + 1)*buf[mid] % (mod - 1)*find_fst(fst[i], L) % (mod - 1);
if (G[P] >= mod - 1)G[P] -= mod - 1;
}
else
{
int bk = nxt[i]>R ? R : nxt[i] - 1;
G[P] += ((LL)(bk - i + 1)*(mid - L + 1) % (mod - 1))*((LL)A[i] * buf[mid] % (mod - 1)) % (mod - 1);
if (G[P] >= mod - 1)G[P] -= mod - 1;
}
}
}
}
}
void BFS_2(int root)
{
int l = 0, r = 1;
queue[0] = root;
while (l < r)
{
int v = queue[l++];
if (D.A[v].c[0])queue[r++] = D.A[v].c[0];
if (D.A[v].c[1])queue[r++] = D.A[v].c[1];
}
while (r--)
{
root = queue[r];
int *c = D.A[root].c;
int L = D.A[root].L;
int R = D.A[root].R;
if (L == R)
{
G[A[buf[L]]] = (G[A[buf[L]]] + buf[L]) % mod_1;
AL[root] = AR[root] = C[root] = A[buf[L]];
continue;
}
int mid = (c[0]) ? D.A[c[0]].R + 1 : D.A[c[1]].L - 1;
int tot = (LL)(mid - L + 1)*(R - mid + 1) % mod_1;
if ((D.A[c[0]].R - D.A[c[0]].L) < (D.A[c[1]].R - D.A[c[1]].L))
{
AR[root] = (LL)AR[c[0]] * AR[c[1]] % mod;
AL[root] = (LL)AL[c[0]] * AL[c[1]] % mod;
C[root] = (LL)C[c[0]] * C[c[1]] % mod;
for (int i = mid; i >= L; i--)
{
int &bk = nxt[i];
if (bk <= mid)continue;
int a = A[buf[i]];
if (bk > R)
{
G[a] += (LL)buf[mid] * (i - L + 1) % mod_1*(R - mid + 1) % mod_1;
if (G[a] >= mod_1)G[a] -= mod_1;
AR[root] = (LL)AR[root] * Pow(A[buf[i]], R - mid + 1) % mod;
int b = (i == mid) ? (fst[i]<L ? L : fst[i] + 1) : mid + 1;
AL[root] = (LL)AL[root] * Pow(A[buf[i]], mid - b + 1) % mod;
if ((i == mid && fst[i] >= L) || i != mid)
C[c[0]] = (LL)C[c[0]] * Pow(A[buf[i]], mod - 2) % mod;
}
else
{
//bk<=R
int b = tot - (LL)(mid - i)*(bk - mid) % mod_1;
if (b < 0)b += mod_1;
G[a] += (LL)buf[mid] * b % mod_1;
if (G[a] >= mod_1)G[a] -= mod_1;
AR[c[1]] = (LL)AR[c[1]] * Pow(A[buf[i]], (LL)(mod - 2)*(R - bk + 1) % mod_1) % mod;
C[c[1]] = (LL)C[c[1]] * Pow(A[buf[i]], mod - 2) % mod;
if (i != mid)
{
C[c[0]] = (LL)C[c[0]] * Pow(A[buf[i]], mod - 2) % mod;
C[root] = (LL)C[root] * Pow(A[buf[i]], mod - 2) % mod;
AL[root] = (LL)AL[root] * Pow(A[buf[i]], mid - i) % mod;
}
else
{
C[c[0]] = (LL)C[c[0]] * (fst[i]<L ? 1 : Pow(A[buf[i]], mod - 2)) % mod;
C[root] = (LL)C[root] * (fst[i]<L ? 1 : Pow(A[buf[i]], mod - 2)) % mod;
AL[root] = (LL)AL[root] * Pow(A[buf[i]], mid + 1 - ((fst[i]<L) ? L : fst[i] + 1)) % mod;
}
AR[root] = (LL)AR[root] * Pow(A[buf[i]], bk - mid) % mod;//
}
}
ans = (LL)ans*Pow(AR[c[1]], (LL)(mid - L + 1)*buf[mid] % (mod - 1)) % mod;
AL[root] = (LL)AL[root] * Pow(C[c[1]], mid - L + 1) % mod;
if (nxt[mid]>R&&fst[mid]<L) C[root] = (LL)C[root] * A[buf[mid]] % mod;
}
else
{
AR[root] = (LL)AR[c[0]] * AR[c[1]] % mod;
AL[root] = (LL)AL[c[0]] * AL[c[1]] % mod;
C[root] = (LL)C[c[0]] * C[c[1]] % mod;
for (int j = mid; j <= R; j++)
{
int &bk = fst[j];
int a = A[buf[j]];
if (bk >= mid)continue;
if (bk < L)
{
G[a] += (LL)buf[mid] * (mid - L + 1) % (mod - 1)*(R - j + 1) % (mod - 1);
if (G[a] >= mod - 1)G[a] -= mod - 1;
AL[root] = (LL)AL[root] * Pow(A[buf[j]], mid - L + 1) % mod;
int b = (j == mid) ? (nxt[j] <= R ? nxt[j] - 1 : R) : mid - 1;
AR[root] = (LL)AR[root] * Pow(A[buf[j]], b - mid + 1) % mod;
if ((j == mid&&nxt[j] <= R) || j != mid)
C[c[1]] = (LL)C[c[1]] * Pow(A[buf[j]], mod - 2) % mod;
}
else
{
int b = tot - (LL)(mid - bk)*(j - mid) % mod_1;
if (b < 0)b += mod_1;
G[a] += (LL)buf[mid] * b % mod_1;
if (G[a] >= mod - 1)G[a] -= mod_1;
AL[c[0]] = (LL)AL[c[0]] * Pow(A[buf[j]], (LL)(bk - L + 1)*(mod - 2) % mod_1) % mod;
C[c[0]] = (LL)C[c[0]] * Pow(A[buf[j]], mod - 2) % mod;
if (j != mid)
{
C[c[1]] = (LL)C[c[1]] * Pow(A[buf[j]], mod - 2) % mod;
C[root] = (LL)C[root] * Pow(A[buf[j]], mod - 2) % mod;
AR[root] = (LL)AR[root] * Pow(A[buf[j]], j - mid) % mod;
}
else
{
C[c[1]] = (LL)C[c[1]] * ((nxt[j] <= R) ? Pow(A[buf[j]], mod - 2) : 1) % mod;
C[root] = (LL)C[root] * ((nxt[j] <= R) ? Pow(A[buf[j]], mod - 2) : 1) % mod;
AR[root] = (LL)AR[root] * Pow(A[buf[mid]], ((nxt[j]>R) ? R : nxt[j] - 1) - mid + 1) % mod;
}
AL[root] = (LL)AL[root] * Pow(A[buf[j]], mid - bk) % mod;
}
}
ans = (LL)ans*Pow(AL[c[0]], (LL)(R - mid + 1)*buf[mid] % mod_1) % mod;
AR[root] = (LL)AR[root] * Pow(C[c[0]], R - mid + 1) % mod;
if (nxt[mid]>R&&fst[mid]<L) C[root] = (LL)C[root] * A[buf[mid]] % mod;
}
}
}
void init(int n)
{
A[0] = A[n + 1] = 0x3f3f3f3f;
for (int i = 2; i < Sqr; i++)
{
if (used[i])continue;
for (int j = i; j < MAXN; j += i) used[j] = 1;
for (int j = 1; j <= n; j++)
{
A[j] = 0;
int t = buf[j];
while (t%i == 0)
{
A[j]++;
t /= i;
}
}
memset(tmp, 0, sizeof tmp);
memset(tmp2, 0, sizeof tmp2);
stk[0] = 0;
for (int j = 1, top = 0; j <= n; j++)
{
while (A[stk[top]] < A[j])top--;
bfst[j] = fst[j] = stk[top];
stk[++top] = j;
}
stk[0] = n + 1;
for (int j = n, top = 0; j; j--)
{
while (A[stk[top]] <= A[j])top--;
bnxt[j] = nxt[j] = stk[top];
stk[++top] = j;
}
BFS_1(D.root, i);
}
for (int i = 0; i < MAXN; i++)A[i] = 1;
for (int i = Sqr; i < MAXN; i++)
{
if (used[i])continue;
for (int j = i; j < MAXN; j += i)
{
used[j] = 1;
A[j] = i;
}
}
memset(tmp, 0, sizeof tmp);
for (int i = 1; i <= n; i++)
{
fst[i] = tmp[A[buf[i]]];
tmp[A[buf[i]]] = i;
}
for (int i = 0; i < MAXN; i++)tmp[i] = n + 1;
for (int j = n; j; j--)
{
nxt[j] = tmp[A[buf[j]]];
tmp[A[buf[j]]] = j;
}
memset(tmp, 0, sizeof tmp);
memset(tmp2, 0, sizeof tmp2);
memset(used, 0, sizeof used);
AL[0] = AR[0] = C[0] = 1;
BFS_2(D.root);
}
int main()
{
int n;
n = I.read();
for (int i = 1; i <= n; i++)
{
buf[i] = I.read();
D.insert(buf[i]);
}
D.BFS(D.root);
init(n);
for (int i = 2; i < MAXN; i++) ans = (LL)ans*Pow(i, G[i]) % mod;
printf("%d\n", ans);
return 0;
}
对于每种P ,我们只需要考虑指数大小。取区间指数最大的那个数就好。
O(nn√∗log2nlogen+nlog22n),题中。最大值和最大元素数量可以同时为n
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <cmath>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const int mod_1 = mod - 1;
const int MAXN = 100003;
const int Sqr = (int)sqrt(MAXN) + 1;
struct Io
{
char A[MAXN * 4],*L,*R;
int count;
Io()
{
L = R = A;
count = MAXN * 4;
}
void Io_fread()
{
L = A;
R = A + fread(A, sizeof(char), count, stdin);
}
int read()
{
int tmp = 0;
if (L == R)
{
Io_fread();
if (L == R)return 0;
}
while (*L<'0'||*L>'9')
{
L++;
if (L == R)
{
Io_fread();
if (L == R)return 0;
}
}
while (*L >= '0'&&*L <= '9')
{
tmp = tmp * 10 + (*L - '0');
L++;
if (L == R)
{
Io_fread();
if (L == R)return tmp;
}
}
return tmp;
}
}I;
int used[MAXN];
int buf[MAXN];
int G[MAXN];
int tmp[MAXN];
int tmp2[MAXN];
int nxt[MAXN];
int fst[MAXN];
int bnxt[MAXN];
int bfst[MAXN];
int queue[MAXN];
int stk[MAXN];
int *wnxt = tmp, *wfst = tmp2, *AL = tmp, *AR = tmp2, *C = used;
int ans = 1;
struct node
{
int c[2];
int L, R;
node()
{
L = R = c[0] = c[1] = 0;
}
};
struct Decare
{
node A[MAXN];
int root;
int deep;
Decare()
{
root = 0;
deep = 1;
}
void _insert(int key, int inof)
{
if (inof == 0)
{
root = deep++;
tmp[root] = key;
return;
}
while (inof)
{
if (tmp[inof] >= key)
{
tmp[deep] = key;
G[deep] = inof;
A[deep].c[0] = A[inof].c[1];
A[inof].c[1] = deep;
G[A[deep].c[0]] = deep;
deep++;
return;
}
inof = G[inof];
}
tmp[deep] = key;
A[deep].c[0] = root;
G[root] = deep;
root = deep++;
}
void insert(int key)
{
_insert(key, deep - 1);
}
void BFS(int root)
{
memset(tmp, 0, sizeof tmp);
int l = 0, r = 1;
stk[0] = root;
while (l < r)
{
int v = stk[l++];
if (A[v].c[0]) stk[r++] = A[v].c[0];
if (A[v].c[1]) stk[r++] = A[v].c[1];
}
int n = r;
while (r--)
{
int v = stk[r];
tmp[v] ++;
tmp[G[v]] += tmp[v];
}
tmp[0] = 0;
l = 0; r = 1;
A[root].L = 1;
A[root].R = n;
A[0].L = 1;
A[0].R = 0;
while (l<r)
{
int v = stk[l++];
A[A[v].c[0]].L = A[v].L;
A[A[v].c[0]].R = A[A[v].c[0]].L + tmp[A[v].c[0]] - 1;
A[A[v].c[1]].L = A[A[v].c[0]].R + 2;
A[A[v].c[1]].R = A[A[v].c[1]].L + tmp[A[v].c[1]] - 1;
if (A[v].c[0]) stk[r++] = A[v].c[0];
if (A[v].c[1]) stk[r++] = A[v].c[1];
}
memset(tmp, 0, sizeof tmp);
memset(G, 0, sizeof G);
A[0].L = 1;
A[0].R = 0;
}
}D;
int Pow(int a, int b)
{
int tmp = 1;
while (b)
{
if (b & 1)
tmp = (LL)tmp*a%mod;
a = (LL)a*a%mod;
b >>= 1;
}
return tmp;
}
int A[MAXN];
int find_nxt(int k, int B)
{
int top = -1, d = k;
while (bnxt[d] <= B)
{
stk[++top] = d;
d = bnxt[d];
}
while (top>-1)
{
int x = stk[top--];
if (bnxt[x] == nxt[x])wnxt[x] = A[x] * (bnxt[x] - x);
wnxt[x] += wnxt[bnxt[x]];
bnxt[x] = d;
}
return wnxt[k] + (B - d + 1)*A[d];
}
int find_fst(int k, int B)
{
int top = -1, d = k;
while (bfst[d] >= B)
{
stk[++top] = d;
d = bfst[d];
}
while (top>-1)
{
int x = stk[top--];
if (bfst[x] == fst[x]) wfst[x] = A[x] * (x - bfst[x]);
wfst[x] += wfst[bfst[x]];
bfst[x] = d;
}
return wfst[k] + (d - B + 1)*A[d];
}
void BFS_1(int root, int P)
{
int l = 0, r = 1;
queue[0] = root;
while (l < r)
{
int v = queue[l++];
if (D.A[v].c[0])queue[r++] = D.A[v].c[0];
if (D.A[v].c[1])queue[r++] = D.A[v].c[1];
}
while (r--)
{
int v = queue[r];
int *c = D.A[v].c;
int L = D.A[v].L;
int R = D.A[v].R;
if (L == R)
{
G[P] = (G[P] + (LL)A[L] * buf[L] % (mod_1)) % mod_1;
continue;
}
int mid = (c[0]) ? D.A[c[0]].R + 1 : D.A[c[1]].L - 1;
if ((D.A[c[0]].R - D.A[c[0]].L + 1)<(D.A[c[1]].R - D.A[c[1]].L + 1))
{
for (int i = mid; i >= L; i = fst[i])
{
if (nxt[i] <= R)
{
int bk = fst[i] < L ? L : fst[i] + 1;
G[P] += ((LL)(i - bk + 1)*(nxt[i] - mid) % (mod - 1))*((LL)A[i] * buf[mid] % (mod - 1)) % (mod - 1);
if (G[P] >= mod - 1)G[P] -= mod - 1;
G[P] += (LL)(i - bk + 1)*(buf[mid]) % (mod - 1)*find_nxt(nxt[i], R) % (mod - 1);
if (G[P] >= mod - 1)G[P] -= mod - 1;
}
else
{
int bk = fst[i]<L ? L : fst[i] + 1;
G[P] += ((LL)(i - bk + 1)*(R - mid + 1) % (mod - 1))*((LL)A[i] * buf[mid] % (mod - 1)) % (mod - 1);
if (G[P] >= mod - 1)G[P] -= mod - 1;
}
}
}
else
{
for (int i = mid; i <= R; i = nxt[i])
{
if (fst[i] >= L)
{
int bk = nxt[i]>R ? R : nxt[i] - 1;
G[P] += ((LL)(bk - i + 1)*(mid - fst[i]) % (mod - 1))*((LL)A[i] * buf[mid] % (mod - 1)) % (mod - 1);
if (G[P] >= mod - 1)G[P] -= mod - 1;;
G[P] += (LL)(bk - i + 1)*buf[mid] % (mod - 1)*find_fst(fst[i], L) % (mod - 1);
if (G[P] >= mod - 1)G[P] -= mod - 1;
}
else
{
int bk = nxt[i]>R ? R : nxt[i] - 1;
G[P] += ((LL)(bk - i + 1)*(mid - L + 1) % (mod - 1))*((LL)A[i] * buf[mid] % (mod - 1)) % (mod - 1);
if (G[P] >= mod - 1)G[P] -= mod - 1;
}
}
}
}
}
void BFS_2(int root)
{
int l = 0, r = 1;
queue[0] = root;
while (l < r)
{
int v = queue[l++];
if (D.A[v].c[0])queue[r++] = D.A[v].c[0];
if (D.A[v].c[1])queue[r++] = D.A[v].c[1];
}
while (r--)
{
root = queue[r];
int *c = D.A[root].c;
int L = D.A[root].L;
int R = D.A[root].R;
if (L == R)
{
G[A[buf[L]]] = (G[A[buf[L]]] + buf[L]) % mod_1;
AL[root] = AR[root] = C[root] = A[buf[L]];
continue;
}
int mid = (c[0]) ? D.A[c[0]].R + 1 : D.A[c[1]].L - 1;
int tot = (LL)(mid - L + 1)*(R - mid + 1) % mod_1;
if ((D.A[c[0]].R - D.A[c[0]].L) < (D.A[c[1]].R - D.A[c[1]].L))
{
AR[root] = (LL)AR[c[0]] * AR[c[1]] % mod;
AL[root] = (LL)AL[c[0]] * AL[c[1]] % mod;
C[root] = (LL)C[c[0]] * C[c[1]] % mod;
for (int i = mid; i >= L; i--)
{
int &bk = nxt[i];
if (bk <= mid)continue;
int a = A[buf[i]];
if (bk > R)
{
G[a] += (LL)buf[mid] * (i - L + 1) % mod_1*(R - mid + 1) % mod_1;
if (G[a] >= mod_1)G[a] -= mod_1;
AR[root] = (LL)AR[root] * Pow(A[buf[i]], R - mid + 1) % mod;
int b = (i == mid) ? (fst[i]<L ? L : fst[i] + 1) : mid + 1;
AL[root] = (LL)AL[root] * Pow(A[buf[i]], mid - b + 1) % mod;
if ((i == mid && fst[i] >= L) || i != mid)
C[c[0]] = (LL)C[c[0]] * Pow(A[buf[i]], mod - 2) % mod;
}
else
{
//bk<=R
int b = tot - (LL)(mid - i)*(bk - mid) % mod_1;
if (b < 0)b += mod_1;
G[a] += (LL)buf[mid] * b % mod_1;
if (G[a] >= mod_1)G[a] -= mod_1;
AR[c[1]] = (LL)AR[c[1]] * Pow(A[buf[i]], (LL)(mod - 2)*(R - bk + 1) % mod_1) % mod;
C[c[1]] = (LL)C[c[1]] * Pow(A[buf[i]], mod - 2) % mod;
if (i != mid)
{
C[c[0]] = (LL)C[c[0]] * Pow(A[buf[i]], mod - 2) % mod;
C[root] = (LL)C[root] * Pow(A[buf[i]], mod - 2) % mod;
AL[root] = (LL)AL[root] * Pow(A[buf[i]], mid - i) % mod;
}
else
{
C[c[0]] = (LL)C[c[0]] * (fst[i]<L ? 1 : Pow(A[buf[i]], mod - 2)) % mod;
C[root] = (LL)C[root] * (fst[i]<L ? 1 : Pow(A[buf[i]], mod - 2)) % mod;
AL[root] = (LL)AL[root] * Pow(A[buf[i]], mid + 1 - ((fst[i]<L) ? L : fst[i] + 1)) % mod;
}
AR[root] = (LL)AR[root] * Pow(A[buf[i]], bk - mid) % mod;//
}
}
ans = (LL)ans*Pow(AR[c[1]], (LL)(mid - L + 1)*buf[mid] % (mod - 1)) % mod;
AL[root] = (LL)AL[root] * Pow(C[c[1]], mid - L + 1) % mod;
if (nxt[mid]>R&&fst[mid]<L) C[root] = (LL)C[root] * A[buf[mid]] % mod;
}
else
{
AR[root] = (LL)AR[c[0]] * AR[c[1]] % mod;
AL[root] = (LL)AL[c[0]] * AL[c[1]] % mod;
C[root] = (LL)C[c[0]] * C[c[1]] % mod;
for (int j = mid; j <= R; j++)
{
int &bk = fst[j];
int a = A[buf[j]];
if (bk >= mid)continue;
if (bk < L)
{
G[a] += (LL)buf[mid] * (mid - L + 1) % (mod - 1)*(R - j + 1) % (mod - 1);
if (G[a] >= mod - 1)G[a] -= mod - 1;
AL[root] = (LL)AL[root] * Pow(A[buf[j]], mid - L + 1) % mod;
int b = (j == mid) ? (nxt[j] <= R ? nxt[j] - 1 : R) : mid - 1;
AR[root] = (LL)AR[root] * Pow(A[buf[j]], b - mid + 1) % mod;
if ((j == mid&&nxt[j] <= R) || j != mid)
C[c[1]] = (LL)C[c[1]] * Pow(A[buf[j]], mod - 2) % mod;
}
else
{
int b = tot - (LL)(mid - bk)*(j - mid) % mod_1;
if (b < 0)b += mod_1;
G[a] += (LL)buf[mid] * b % mod_1;
if (G[a] >= mod - 1)G[a] -= mod_1;
AL[c[0]] = (LL)AL[c[0]] * Pow(A[buf[j]], (LL)(bk - L + 1)*(mod - 2) % mod_1) % mod;
C[c[0]] = (LL)C[c[0]] * Pow(A[buf[j]], mod - 2) % mod;
if (j != mid)
{
C[c[1]] = (LL)C[c[1]] * Pow(A[buf[j]], mod - 2) % mod;
C[root] = (LL)C[root] * Pow(A[buf[j]], mod - 2) % mod;
AR[root] = (LL)AR[root] * Pow(A[buf[j]], j - mid) % mod;
}
else
{
C[c[1]] = (LL)C[c[1]] * ((nxt[j] <= R) ? Pow(A[buf[j]], mod - 2) : 1) % mod;
C[root] = (LL)C[root] * ((nxt[j] <= R) ? Pow(A[buf[j]], mod - 2) : 1) % mod;
AR[root] = (LL)AR[root] * Pow(A[buf[mid]], ((nxt[j]>R) ? R : nxt[j] - 1) - mid + 1) % mod;
}
AL[root] = (LL)AL[root] * Pow(A[buf[j]], mid - bk) % mod;
}
}
ans = (LL)ans*Pow(AL[c[0]], (LL)(R - mid + 1)*buf[mid] % mod_1) % mod;
AR[root] = (LL)AR[root] * Pow(C[c[0]], R - mid + 1) % mod;
if (nxt[mid]>R&&fst[mid]<L) C[root] = (LL)C[root] * A[buf[mid]] % mod;
}
}
}
void init(int n)
{
A[0] = A[n + 1] = 0x3f3f3f3f;
for (int i = 2; i < Sqr; i++)
{
if (used[i])continue;
for (int j = i; j < MAXN; j += i) used[j] = 1;
for (int j = 1; j <= n; j++)
{
A[j] = 0;
int t = buf[j];
while (t%i == 0)
{
A[j]++;
t /= i;
}
}
memset(tmp, 0, sizeof tmp);
memset(tmp2, 0, sizeof tmp2);
stk[0] = 0;
for (int j = 1, top = 0; j <= n; j++)
{
while (A[stk[top]] < A[j])top--;
bfst[j] = fst[j] = stk[top];
stk[++top] = j;
}
stk[0] = n + 1;
for (int j = n, top = 0; j; j--)
{
while (A[stk[top]] <= A[j])top--;
bnxt[j] = nxt[j] = stk[top];
stk[++top] = j;
}
BFS_1(D.root, i);
}
for (int i = 0; i < MAXN; i++)A[i] = 1;
for (int i = Sqr; i < MAXN; i++)
{
if (used[i])continue;
for (int j = i; j < MAXN; j += i)
{
used[j] = 1;
A[j] = i;
}
}
memset(tmp, 0, sizeof tmp);
for (int i = 1; i <= n; i++)
{
fst[i] = tmp[A[buf[i]]];
tmp[A[buf[i]]] = i;
}
for (int i = 0; i < MAXN; i++)tmp[i] = n + 1;
for (int j = n; j; j--)
{
nxt[j] = tmp[A[buf[j]]];
tmp[A[buf[j]]] = j;
}
memset(tmp, 0, sizeof tmp);
memset(tmp2, 0, sizeof tmp2);
memset(used, 0, sizeof used);
AL[0] = AR[0] = C[0] = 1;
BFS_2(D.root);
}
int main()
{
int n;
n = I.read();
for (int i = 1; i <= n; i++)
{
buf[i] = I.read();
D.insert(buf[i]);
}
D.BFS(D.root);
init(n);
for (int i = 2; i < MAXN; i++) ans = (LL)ans*Pow(i, G[i]) % mod;
printf("%d\n", ans);
return 0;
}