【Tsinsen A1339】JZPLCM (树状数组)
Description
给定一长度为\(~n~\)的正整数序列\(~a~\),有\(~q~\)次询问,每次询问一段区间内所有数的\(~LCM~\)(即最小公倍数)。由于答案可能很大,输出答案模\(~1e9 + 7~\)。\(~1 \leq n \leq 10 ^ 5~\),\(~1 \leq a_i \leq 10 ^ 9~\).
Solution
看到这个题,第一感觉就是\(~O(n ^ 3)~\)暴力求\(~LCM~\),可是发现这有个模数,扫一遍求\(~LCM~\)不现实。但的确我们可以从这个模数下手,来推到导\(~LCM~\)的一些性质。首先,对于一段数的\(~LCM~\),不难发现就是其分解质因数后不同因子出现的最大幂次的乘积。对于序列中的每一个数\(~x~\)都可以分解成\(~x = \prod p_i ^ {k_i}~\),可以把每一个\(~p_i ^ {k_ i}~\)都想象成为\(~k_i~\)个物品\(~p_{i,1}, ~p_{i,2}, ..., p_{i,{k_i}}~\),每个物品的权值为\(~p_i~\),原问题求得是相同\(~p_i~\)的最高次幂是多少,这个求区间不同物品的权值之和,不难发现这是等价的。
考虑离线,把询问按右端点从小到大排序,每一次处理出右端点为\(~i~\)的答案,对于\(~i~\)的所有物品,都在树状数组的\(~i~\)位置乘上这个权值,在这个物品上一次出现的位置除以这个权值,再对右端点为\(~i~\)的询问更新即可。这个巧妙的求区间不同的元素个数的离线套路好像很经典。
Code
#include<bits/stdc++.h>
#define For(i, j, k) for(int i = j; i <= k; ++i)
#define Forr(i, j, k) for(int i = j; i >= k; --i)
using namespace std;
inline int read() {
int x = 0, p = 1; char c = getchar();
for(; !isdigit(c); c = getchar()) if(c == '-') p = -1;
for(; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x *= p;
}
inline void File() {
freopen("A1339.in", "r", stdin);
freopen("A1339.out", "w", stdout);
}
typedef long long ll;
const int N = 1e5 + 10, mod = 1e9 + 7;
int n, q, a[N], prime[N], isnot[N], cnt, ans[N], inv[N];
struct node { int l, r, id; } Q[N];
unordered_map<int, int> las;
inline bool cmp(const node &a, const node &b) { return a.r < b.r; }
inline void Init(int n) {
isnot[1] = 1;
For(i, 2, n) {
if (!isnot[i]) prime[++ cnt] = i;
For(j, 1, cnt) {
if (1ll * i * prime[j] > n) break;
isnot[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
}
}
}
inline int qpow(int a, int b) {
static int res;
for (res = 1; b; a = 1ll * a * a % mod, b >>= 1)
if (b & 1) res = 1ll * a * res % mod;
return res;
}
struct BIT {
int c[N];
inline void mul(int x, int v) {
for (; x <= n; x += x & -x) c[x] = 1ll * c[x] * v % mod;
}
inline int query(int x) {
int res = 1;
for (; x; x -= x & -x) res = 1ll * res * c[x] % mod;
return res;
}
} T;
int main() {
File(), Init(31630);
n = read(), q = read();
For(i, 1, n) a[i] = read(), T.c[i] = 1;
For(i, 1, q) Q[i].l = read(), Q[i].r = read(), Q[i].id = i;
sort(Q + 1, Q + 1 + q, cmp);
For(i, 1, cnt) inv[i] = qpow(prime[i], mod - 2);
for (int i = 1, l = 1; i <= n; ++ i) {
int tmp = a[i];
for (int j = 1; prime[j] <= tmp && j <= cnt; ++ j) {
if (tmp % prime[j] != 0) continue;
for (int k = prime[j], lst; tmp % prime[j] == 0; k *= prime[j], tmp /= prime[j]) {
T.mul(i, prime[j]), lst = las[k];
if (lst) T.mul(lst, inv[j]);
las[k] = i;
}
}
if (tmp > 1) {
T.mul(i, tmp); int lst = las[tmp];
if (lst) T.mul(lst, qpow(tmp, mod - 2));
las[tmp] = i;
}
int res = T.query(i);
while (l <= q && Q[l].r == i) ans[Q[l].id] = 1ll * res * qpow(T.query(Q[l].l - 1), mod - 2) % mod, ++ l;
}
For(i, 1, q) printf("%d\n", ans[i]);
return 0;
}
【Tsinsen A1339】JZPLCM (树状数组)的更多相关文章
- BZOJ 1103: [POI2007]大都市meg [DFS序 树状数组]
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2221 Solved: 1179[Submit][Sta ...
- bzoj1878--离线+树状数组
这题在线做很麻烦,所以我们选择离线. 首先预处理出数组next[i]表示i这个位置的颜色下一次出现的位置. 然后对与每种颜色第一次出现的位置x,将a[x]++. 将每个询问按左端点排序,再从左往右扫, ...
- codeforces 597C C. Subsequences(dp+树状数组)
题目链接: C. Subsequences time limit per test 1 second memory limit per test 256 megabytes input standar ...
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
- BZOJ 3529: [Sdoi2014]数表 [莫比乌斯反演 树状数组]
3529: [Sdoi2014]数表 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1399 Solved: 694[Submit][Status] ...
- BZOJ 3289: Mato的文件管理[莫队算法 树状数组]
3289: Mato的文件管理 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 2399 Solved: 988[Submit][Status][Di ...
- 【Codeforces163E】e-Government AC自动机fail树 + DFS序 + 树状数组
E. e-Government time limit per test:1 second memory limit per test:256 megabytes input:standard inpu ...
- 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序
3881: [Coci2015]Divljak Time Limit: 20 Sec Memory Limit: 768 MBSubmit: 508 Solved: 158[Submit][Sta ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
随机推荐
- 福州大学软件工程1816 | W班 第2次作业成绩排名
作业链接 词频统计基础功能 评分细则 本次个人项目分数由两部分组成(博客分满分40分+程序得分满分60分) 博客评分规则 在文章开头给出你们Fork仓库的Github项目地址.(1') 在开始实现程序 ...
- PHP的优化建议(仅借鉴)
转载: https://www.awaimai.com/1050.html 1 字符串 1.1 少用正则表达式 能用PHP内部字符串操作函数的情况下,尽量用他们,不要用正则表达式, 因为其效率高于正则 ...
- 六、es6 map
一.map的特点 JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键.这给它的使用带来了很大的限制. 为了解决这个问题,ES6 提供了 ...
- 解决.Net Mvc跨域请求问题
针对ASP.NET MVC和ASP.NET Web API两种项目类型 1.针对ASP.NET MVC,只需要在web.config中添加如下的内容即可 <system.webServer> ...
- python学习笔记(5)-基本数据类型-字符串类型及操作
一.字符串 字符串由一对单引号或者双引号表示,如”abc“,‘中国’,字符串是字符的有序序列,可以对其中的字符进行索引.字符串也可以用三单引号或三双引号表示,可以表示多行字符串,一对单引号或双引号仅表 ...
- 莫烦scikit-learn学习自修第五天【训练模型的属性】
1.代码实战 #!/usr/bin/env python #!_*_ coding:UTF-8 _*_ from sklearn import datasets from sklearn.linear ...
- 老男孩python学习自修【第一天】文件IO用法
第一天 文件IO处理 1.读文件实例 file_split.python f = file('myFile.txt', 'r') for line in f.readlines(): line = ...
- springboot+jpa+mysql+swagger整合
Springboot+jpa+MySQL+swagger整合 创建一个springboot web项目 <dependencies> <dependency> < ...
- js 中常用的循环
参考文章: 1.js几种数组遍历方式以及性能分析对比 2.javaScript遍历对象.数组总结 首先是数组中可以使用的 1.for 循环 for (let i = 0; i < xxx.len ...
- Software License Manager
slmgr -ilc lenovo.xrm-ms slmgr -ipk lenovo-lenovo-lenovo-lenovo-lenovo