据说这是某国家队爷的题,怪不得我一眼不会。
求lcm即求各个质因子对应得指数的最大值。
这时候想到以前做过几道类似的题怎么做的。
把 <n√ 的质因子分成一块,大于 >n√ 的质因子分成一块。
这样做的优势是
<n√
的质因子的个数少,
而,
>n√
的质因子的指数最大为1。
那么这道题就显然了。
<n√ 的质因子强行RMQ,因为只有48个。
>n√ 的质因子因为指数小于等于1,可以直接上莫队,提前处理一下逆元就好了。
时间复杂度 O(48∗n log n+nn√)
Code:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
using namespace std;
const int N = 50005, M = 223;
int bz[N], p[N], zp[N];
void Shai() {
fo(i, 2, 5e4) {
if(!bz[i]) p[++ p[0]] = i;
fo(j, 1, p[0]) {
if(i * p[j] > 5e4) break;
bz[i * p[j]] = 1;
if(i % p[j] == 0) break;
}
}
int t = 0;
fo(i, 2, 5e4) if(!bz[i])
zp[i] = ++ t;
}
int num[N];
void Build() {
int tot = 0;
fo(i, 1, 5e4) {
num[i] = num[i - 1];
if((i - 1) % M == 0) num[i] ++;
}
}
int n, Q, x, y, a[N], p0[N], u[N][20], v[N][20];
struct Ask {
int l, r, i;
} c[N];
void fen(int a, int x) {
p0[a] = 0;
for(int i = 1; i <= p[0] && p[i] * p[i] <= x; i ++) {
if(x % p[i] == 0) {
u[a][++ p0[a]] = i;
v[a][p0[a]] = 0;
while(x % p[i] == 0)
x /= p[i], v[a][p0[a]] ++;
}
}
if(x > 1) {
u[a][++ p0[a]] = zp[x];
v[a][p0[a]] = 1;
}
}
bool rank_c(Ask a, Ask b) {
if(num[a.l] < num[b.l]) return 1;
if(num[a.l] > num[b.l]) return 0;
return a.r < b.r;
}
int f[16][N], a2[16];
int query(int i, int j) {
int lg = log2(j - i + 1);
return max(f[lg][i], f[lg][j - a2[lg] + 1]);
}
const int mo = 1e9 + 7;
ll ksm(ll x, ll y) {
ll s = 1;
for(; y; y >>= 1, x = x * x % mo)
if(y & 1) s = s * x % mo;
return s;
}
ll ni[N], ans[N];
ll sum;
int t[N];
void add(int x, int y) {
t[x] += y;
if(t[x] == 0) sum = sum * ni[x] % mo;
if(t[x] == 1 && y == 1) sum = sum * p[x] % mo;
}
void chan(int x) {
int k = bz[x] ? -1 : 1; bz[x] = !bz[x];
fo(i, 1, p0[x]) if(u[x][i] > 48)
add(u[x][i], k);
}
int main() {
Shai();
Build();
scanf("%d %d", &n, &Q);
fo(i, 1, n) scanf("%d", &a[i]), fen(i, a[i]);
fo(i, 1, Q) scanf("%d %d", &c[i].l, &c[i].r), c[i].i = i;
fo(i, 1, Q) ans[i] = 1;
a2[0] = 1; fo(i, 1, 15) a2[i] = a2[i - 1] * 2;
fo(k, 1, 48) {
fo(i, 1, n) f[0][i] = 0;
fo(i, 1, n) fo(j, 1, p0[i])
if(u[i][j] == k) f[0][i] = v[i][j];
fo(j, 1, 15) fo(i, 1, n) f[j][i] = max(f[j - 1][i], f[j - 1][min(i + a2[j - 1], n)]);
fo(i, 1, Q) ans[i] = ans[i] * ksm(p[k], query(c[i].l, c[i].r)) % mo;
}
sort(c + 1, c + Q + 1, rank_c);
fo(i, 1, p[0]) ni[i] = ksm(p[i], mo - 2);
memset(bz, 0, sizeof(bz));
int x = 1, y = 0; sum = 1;
fo(i, 1, Q) {
while(x < c[i].l) chan(x ++);
while(x > c[i].l) chan(-- x);
while(y < c[i].r) chan(++ y);
while(y > c[i].r) chan(y --);
ans[c[i].i] = ans[c[i].i] * sum % mo;
}
fo(i, 1, Q) printf("%lld\n", ans[i]);
}