您的位置:首页 > 其它

51nod 1203 JZPLCM

2017-11-23 18:40 169 查看
原题链接.

据说这是某国家队爷的题,怪不得我一眼不会。

求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
, p
, zp
;

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
;

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
, p0
, u
[20], v
[20];

struct Ask {
int l, r, i;
} c
;

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]
, 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
, ans
;

ll sum;

int t
;

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]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: