L C M LCM LCM
给 你 一 个 长 度 为 N 的 数 列 , 有 M 次 询 问 , 每 次 询 问 一 段 区 间 的 L C M 模 1 e 9 + 7 的 值 . 给你一个长度为 N 的数列,有 M 次询问,每次询问一段区间的 LCM 模 1e9+7 的值 . 给你一个长度为N的数列,有M次询问,每次询问一段区间的LCM模1e9+7的值.
1 ≤ N ≤ 200000 1 ≤ M ≤ 200000 1 ≤ A i ≤ 1000000 1 ≤ N ≤ 200000\ 1 ≤ M ≤ 200000\ 1 ≤ Ai ≤ 1000000 1≤N≤200000 1≤M≤200000 1≤Ai≤1000000
正 解 部 分 \color{red}{正解部分} 正解部分
类似 ‘HH的项链’ 的做法,
将所有询问离线, 按 右端点 从小到大 排序, 然后 从左向右 枚举 i i i,
首先对当前位置的
A
[
i
]
A[i]
A[i] 进行 质因数 分解, 记
l
a
s
t
[
p
k
]
last[p^k]
last[pk] 表示
p
k
p^k
pk 这个因子在
i
i
i 前面最晚出现的位置,
使用 树状数组 维护 前缀积, 若
A
[
i
]
A[i]
A[i] 含有质因子
p
m
p^m
pm, 则对
l
a
s
t
[
p
1
]
,
l
a
s
t
[
p
2
]
.
.
.
l
a
s
t
[
p
m
]
last[p^1], last[p^2]...last[p^m]
last[p1],last[p2]...last[pm] 位置上的值 除
p
p
p, 使
l
a
s
t
[
p
k
]
=
i
last[p^k]=i
last[pk]=i, 最后在
i
i
i 位置上 乘
m
m
m 次
p
p
p,
实 现 部 分 \color{red}{实现部分} 实现部分
#include<bits/stdc++.h>
#define reg register
const int maxn = 1e6 + 5;
const int mod = 1e9 + 7;
int N;
int M;
int pcnt;
int p[maxn];
int A[maxn];
int fm[maxn];
int Ans[maxn];
int last[maxn];
bool vis[maxn];
void sieve(){
for(reg int i = 2; i < maxn; i ++){
if(!vis[i]) p[++ pcnt] = i, fm[i] = i;
for(reg int j = 1; j <= pcnt && i*p[j] < maxn; j ++){
vis[i*p[j]] = 1; fm[i*p[j]] = p[j];
if(i % p[j] == 0) break ;
}
}
}
int Ksm(int a, int b){int s=1;while(b){ if(b&1)s=1ll*s*a%mod;a=1ll*a*a%mod;b>>=1; }return s;}
struct Que{ int l, r, id; } que[maxn];
struct Bit_Tree{
int v[maxn], lim;
void Add(int k, int x){ while(k<=lim)v[k]=1ll*v[k]*x%mod,k+=k&-k; }
int Query(int k){ if(k<=0) return 1; int s=1; while(k)s=1ll*s*v[k]%mod,k-=k&-k; return s; }
} bit_t;
bool cmp(Que a, Que b){ return a.r < b.r; }
int main(){
sieve();
scanf("%d%d", &N, &M); bit_t.lim = N;
for(reg int i = 1; i <= N; i ++) scanf("%d", &A[i]), bit_t.v[i] = 1;
for(reg int i = 1; i <= M; i ++) scanf("%d%d", &que[i].l, &que[i].r), que[i].id = i;
std::sort(que+1, que+M+1, cmp); int t = 1;
for(reg int i = 1; i <= N; i ++){
int x = A[i];
while(x > 1){
int k = 1, p = fm[x];
while(x%p == 0){
x /= p, k *= p;
if(last[k]) bit_t.Add(last[k], Ksm(p, mod-2));
last[k] = i; bit_t.Add(i, p);
}
}
while(i == que[t].r) Ans[que[t].id] = 1ll*bit_t.Query(que[t].r)*Ksm(bit_t.Query(que[t].l-1), mod-2)%mod, t ++;
}
for(reg int i = 1; i <= M; i ++) printf("%d\n", Ans[i]);
return 0;
}