不算很难的一道题

原题的数据虽然很小,但是我们不能欺负它,我们就要当$S[i] \leqslant 10^9$来做这题

最小公倍数 = 所有的质因数取可能的最大幂相乘

对于$> \sqrt S$的质数,幂只会为$0$或者$1$,只要维护有没有存在即可

对于$< \sqrt S$的质数,在$S[i] \leqslant 50000$时,我们可以暴力对每个质数维护相应地幂次

但是在$S[i] \leqslant 10^9$时,我们考虑把$p, p^2, p^3, ....$单独看做一种质数,每种质数都有$p$的贡献来维护

由于删除操作不好做,因此考虑离线扫描线做到只有插入

左端点从右到左扫,只要维护右端点的答案即可

可以发现,每种质数出现的区间一定是一段后缀,因此可以考虑维护后缀积来快速回答

每次扫描线加入点时,只要分解这个点,然后把相应地质数的后缀积改变即可

如果$S[i] \leqslant 50000$,那么复杂度可以做到$O(n \log^2 n + q \log n)$

否则,复杂度可以做到$O(n v(n) + n \log^2 n + q \log n)$,其中$v(n)$为分解$n$的复杂度

#include <map>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; extern inline char gc() {
static char RR[], *S = RR + , *T = RR + ;
if(S == T) fread(RR, , , stdin), S = RR;
return *S ++;
}
inline int read() {
int p = , w = ; char c = gc();
while(c > '' || c < '') { if(c == '-') w = -; c = gc(); }
while(c >= '' && c <= '') p = p * + c - '', c = gc();
return p * w;
} #define ri register int
#define sid 50005
const int mod = ; int n, Q;
int v[sid], ans[sid];
struct Ask {
int l, r, id;
friend bool operator < (Ask a, Ask b)
{ return a.l > b.l; }
} q[sid]; int inv[sid], pre[sid];
int nop[sid], pr[sid], mp[sid], tot;
void Sieve() {
for(ri i = ; i <= ; i ++) {
if(!nop[i]) pr[++ tot] = i, mp[i] = i;
for(ri j = ; j <= tot; j ++) {
int p = i * pr[j]; if(p > ) break;
nop[p] = ; mp[p] = pr[j];
if(i % pr[j] == ) break;
}
}
inv[] = ;
for(ri i = ; i <= ; i ++)
inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
} int val[sid << ]; #define ls (o << 1)
#define rs (o << 1 | 1)
inline void inh(int o) { val[o] = 1ll * val[ls] * val[rs] % mod; } void build(int o, int l, int r) {
val[o] = ; if(l == r) return;
int mid = (l + r) >> ;
build(ls, l, mid); build(rs, mid + , r);
} void upd(int o, int l, int r, int p, int v, int opt) {
if(l == r) {
if(opt == ) val[o] = 1ll * val[o] * v % mod;
else val[o] = 1ll * val[o] * inv[v] % mod;
return;
}
int mid = (l + r) >> ;
if(p <= mid) upd(ls, l, mid, p, v, opt);
else upd(rs, mid + , r, p, v, opt);
inh(o);
} int qry(int o, int l, int r, int ml, int mr) {
if(ml > r || mr < l) return ;
if(ml <= l && mr >= r) return val[o];
int mid = (l + r) >> ;
return 1ll * qry(ls, l, mid, ml, mr) * qry(rs, mid + , r, ml, mr) % mod;
} void solve(int v, int c, int now) {
if(!v) return; int w = ;
for(ri i = ; i <= c; i ++) {
w = w * v;
if(pre[w]) upd(, , n, pre[w], v, -);
upd(, , n, now, v, ); pre[w] = now;
}
} void add(int o) {
int w = v[o], lstp = , cnt = ;
while() {
if(mp[w] != lstp)
solve(lstp, cnt, o), lstp = mp[w], cnt = ;
else cnt ++;
if(w == ) break; w /= mp[w];
}
} int main() { n = read(); Q = read(); Sieve();
for(ri i = ; i <= n; i ++) v[i] = read(); for(ri i = ; i <= Q; i ++)
q[i].id = i, q[i].l = read(), q[i].r = read();
sort(q + , q + Q + ); build(, , n);
for(ri i = n, j = ; i >= ; i --) {
add(i);
while(q[j].l == i && j <= Q)
ans[q[j].id] = qry(, , n, i, q[j].r), j ++;
} for(ri i = ; i <= Q; i ++) printf("%d\n", ans[i]);
return ;
}

51nod1203 JZPLCM 线段树 + 扫描线的更多相关文章

  1. 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)

    D. Slalom time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...

  2. Codeforces VK CUP 2015 D. Closest Equals(线段树+扫描线)

    题目链接:http://codeforces.com/contest/522/problem/D 题目大意:  给你一个长度为n的序列,然后有m次查询,每次查询输入一个区间[li,lj],对于每一个查 ...

  3. 【POJ-2482】Stars in your window 线段树 + 扫描线

    Stars in Your Window Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11706   Accepted:  ...

  4. HDU 4419 Colourful Rectangle --离散化+线段树扫描线

    题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...

  5. BZOJ-3228 棋盘控制 线段树+扫描线+鬼畜毒瘤

    3228: [Sdoi2008]棋盘控制 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 23 Solved: 9 [Submit][Status][D ...

  6. BZOJ-3225 立方体覆盖 线段树+扫描线+乱搞

    看数据范围像是个暴力,而且理论复杂度似乎可行,然后被卡了两个点...然后来了个乱搞的线段树+扫描线.. 3225: [Sdoi2008]立方体覆盖 Time Limit: 2 Sec Memory L ...

  7. hdu 5091(线段树+扫描线)

    上海邀请赛的一道题目,看比赛时很多队伍水过去了,当时还想了好久却没有发现这题有什么水题的性质,原来是道成题. 最近学习了下线段树扫描线才发现确实是挺水的一道题. hdu5091 #include &l ...

  8. POJ1151+线段树+扫描线

    /* 线段树+扫描线+离散化 求多个矩形的面积 */ #include<stdio.h> #include<string.h> #include<stdlib.h> ...

  9. POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]

    题意:求矩形面积并 分析:使用线段树+扫描线...因为坐标是浮点数的,因此还需要离散化! 把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用col表示该区间有多少个下边,sum代表该区 ...

随机推荐

  1. 【BZOJ】2165: 大楼

    [题意]从第0层开始有无穷层,每层有n个房间,给定矩阵A,A[i][j]表示从第x层的房间 i 可以跳到第x+A[i][j]层的房间 j (x任意),A[i][j]=0表示不能跳.初始在第0层第1个房 ...

  2. 【洛谷 P2865】 [USACO06NOV]路障Roadblocks(最短路)

    题目链接 次短路模板题. 对每个点记录最短路和严格次短路,然后就是维护次值的方法了. 和这题一样. #include <cstdio> #include <queue> #in ...

  3. 【leetcode 简单】 第三十五题 环形链表

    给定一个链表,判断链表中是否有环. 进阶: 你能否不使用额外空间解决此题? /** * Definition for singly-linked list. * struct ListNode { * ...

  4. 2017ACM暑期多校联合训练 - Team 6 1010 HDU 6105 Gameia (博弈)

    题目链接 Problem Description Alice and Bob are playing a game called 'Gameia ? Gameia !'. The game goes ...

  5. spring-boot 更换依赖版本

    创建Spring Boot操作步骤如下: 在File菜单里面选择 New > Project,然后选择Spring Initializr 更换版本 或 pom spring-boot-start ...

  6. SQL server(到主机的TCPIPl连接失败的问题)

    1 首先要做的是在sql新建查询里输入 exec sys.sp_readerrorlog 0, 1, 'listening' 运行后 会显示你的sql 正在运行的tcp/ip接口 看看是否和你java ...

  7. 给vim安装YouCompleteMe

    要安装YouCompleteMe ,vim须支持python.看是否支持,可以在vim中:version 查看, 如果python前有+号,就是支持,减号就是不支持. 如果不支持,需要以编译安装方式重 ...

  8. Mysql 主主复制失败恢复【转】

    Mysql 主主复制失败 Mysql 主主复制失败 故障描述 架构信息 节点信息 故障分析 同步AIPPRD2的从环境 同步AIPPRD1的从环境 故障描述 原因描述 因为机柜PDU老化, 导致整个机 ...

  9. beego学习笔记(4):开发文档阅读(5)

    controller的逻辑: 我们看下面的代码,就知道怎么传值的: import ( "github.com/astaxie/beego" ) type MainControlle ...

  10. Go语言入门之切片的概念

    切片是对数组的抽象,对切片的改变会改变原数组的值 package main import "fmt" func test6(){ arr:=[...],,,,,,,,,,} s1: ...