题意:
给出一个长度为 n 的序列 a,q次询问 ∏ i = l r lcm ( a i , x ) \prod\limits_{i=l}^r \operatorname{lcm}(a_i,x) i=l∏rlcm(ai,x) 的值。
答案对 1 0 9 + 7 10 ^ 9 + 7 109+7取模。
思路:
∏
i
=
l
r
l
c
m
(
a
i
,
x
)
=
∏
i
=
l
r
a
i
x
g
c
d
(
a
i
,
x
)
=
∏
i
=
l
r
a
i
x
∏
i
=
l
r
g
c
d
(
a
i
,
x
)
\begin{aligned} &\prod_{{i=l}}^rlcm(a_i,x)\\ =&\prod_{i=l}^r\frac{a_ix}{gcd(a_i,x)}\\ =&\frac{\prod\limits_{i=l}^ra_ix}{\prod\limits_{i=l}^rgcd(a_i,x)}\\ \end{aligned}
==i=l∏rlcm(ai,x)i=l∏rgcd(ai,x)aixi=l∏rgcd(ai,x)i=l∏raix
公式上半部分预处理
下半部分
{
x
=
∏
i
=
1
k
p
x
i
q
x
i
a
i
=
∏
j
=
1
k
p
i
j
q
i
j
∏
i
=
l
r
g
c
d
(
a
i
,
x
)
=
∏
i
=
l
r
∏
j
=
1
k
p
x
j
m
i
n
(
q
i
j
,
q
x
j
)
=
∏
i
=
1
k
p
x
i
∑
j
=
l
r
m
i
n
(
q
j
i
,
q
x
i
)
=
∏
i
=
1
k
p
x
i
∑
d
=
1
q
x
i
∑
j
=
l
r
[
d
≤
q
j
i
]
=
∏
i
=
1
k
p
x
i
∑
d
=
1
q
x
i
∑
j
=
l
r
[
p
x
i
d
∣
p
x
i
q
j
i
]
=
∏
i
=
1
k
p
x
i
∑
d
=
1
q
x
i
∑
j
=
l
r
[
p
x
i
d
∣
a
j
]
\begin{cases} x&=&\prod_{i=1}^kp_{xi}^{q_{xi}}\\ a_i&=&\prod_{j=1}^kp_{ij}^{q_{ij}} \end{cases}\\ \begin{aligned} &\prod_{i=l}^rgcd(a_i,x)\\ =&\prod_{i=l}^r\prod_{j=1}^kp_{xj}^{min(q_{ij},q_{xj})}\\ =&\prod_{i=1}^kp_{xi}^{\sum\limits_{j=l}^rmin(q_{ji},q_{xi})}\\ =&\prod_{i=1}^kp_{xi}^{\sum\limits_{d=1}^{q_{xi}}\sum\limits_{j=l}^r[d\le q_{ji}]}\\ =&\prod_{i=1}^kp_{xi}^{\sum\limits_{d=1}^{q_{xi}}\sum\limits_{j=l}^r[p_{xi}^d|p_{xi}^{q_{ji}}]}\\ =&\prod_{i=1}^kp_{xi}^{\sum\limits_{d=1}^{q_{xi}}\sum\limits_{j=l}^r[p_{xi}^d|a_j]}\\ \end{aligned}
{xai==∏i=1kpxiqxi∏j=1kpijqij=====i=l∏rgcd(ai,x)i=l∏rj=1∏kpxjmin(qij,qxj)i=1∏kpxij=l∑rmin(qji,qxi)i=1∏kpxid=1∑qxij=l∑r[d≤qji]i=1∏kpxid=1∑qxij=l∑r[pxid∣pxiqji]i=1∏kpxid=1∑qxij=l∑r[pxid∣aj]
先预处理出每个 a i a_i ai是哪些 p i j p_{ij} pij的倍数,用数组存下下标,对于一个区间 [ l , r ] [l,r] [l,r],我们只需要求出 x x x的某个贡献 p x j k ( k ∈ ( 1 , q x j ) ) p_{xj}^k(k\in(1,q_{xj})) pxjk(k∈(1,qxj))
中包含在 [ l , r ] [l,r] [l,r]区间的下标有多少个。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e5+10;
const int mod = 1e9+7;
ll fac[N];
int p[N], last[N], tot;
bool st[N];
vector<int> pr[N];
void init() {
fac[0] = last[1] = 1;
for(int i=2; i<N; i++) {
if(!st[i]) p[tot++] = i, last[i] = i;
for(int j=0; j<tot&&1ll*i*p[j]<N; j++) {
st[i*p[j]] = 1;
last[i*p[j]] = p[j];
if(i % p[j] == 0) break;
}
}
}
ll qpow(ll x, ll y) {
ll ans = 1;
while(y) {
if(y & 1) ans = ans * x % mod;
x = x * x % mod;
y >>= 1;
}
return ans;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
init();
int n, m, x;
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++) {
scanf("%d", &x);
fac[i] = fac[i-1] * x % mod;
int tmp = x;
while(tmp != 1) {
int u = last[tmp], v = 1;
while(tmp % u == 0) {
tmp /= u;
v *= u;
pr[v].push_back(i);
}
}
}
int l, r;
for(int i=1; i<=m; i++) {
scanf("%d%d%d", &l, &r, &x);
int tmp = x;
ll res = 1;
while(tmp != 1) {
int u = last[tmp], v = 1, cnt = 0;
while(tmp % u == 0) {
tmp /= u;
v *= u;
cnt += upper_bound(pr[v].begin(), pr[v].end(), r)-lower_bound(pr[v].begin(), pr[v].end(), l);
}
res = res * qpow(u, cnt) % mod;
}
printf("%lld\n", fac[r]*qpow(fac[l-1], mod-2)%mod*qpow(x, r-l+1)%mod*qpow(res, mod-2)%mod);
}
return 0;
}