【TsinsenA1339】JZPLCM(顾昱洲) 树状数组
试题来源
2012中国国家集训队命题答辩
问题描述
给定一长度为n的正整数序列a,有q次询问,每次询问一段区间内所有数的lcm(即最小公倍数)。由于答案可能很大,输出答案模1000000007。
输入格式
第一行,两个整数,n, q,分别表示数列长度和询问个数。
下面n行,每行一个整数,第i行的整数为ai。
下面q行,每行两个整数l, r,表示询问下标i在[l, r]范围内的ai的lcm。
输出格式
q行。对于每个询问,输出一行,表示对应的答案。
样例输入
3 3
123
234
345
1 2
2 3
1 3
样例输出
9594
26910
1103310
数据规模和约定
测试数据编号 | 规模和约定 |
---|---|
1, 2 | n, q<=1000 |
3, 4 | n, q<=5000 |
5, 6 | n, q<=20000 |
7, 8 | n, q<=30000 |
9, 10 | n, q<=40000 |
11, 12 | n, q<=50000 |
13, 14 | n, q<=80000 |
15, 16 | n, q<=100000 |
17, 18, 19, 20 | n, q<=100000 数列a中每个数能表示为不超过100的素数的积 |
对于所有测试点,数列a中每个数满足1<=ai<=1000000000。
求LCM会爆LL,所以可以考虑分解质因数然后求最大幂然后乘起来。
40分算法:
对于最后四个点:
考虑对每个素数的幂建一个ST表,则答案是每个素数的幂的区间最大值,乘起来就行了。复杂度O(25∗nlogn+25q)O(25*nlogn+25q)。
对于前四个点:
暴力分解质因数,求最大的幂。复杂度O(nqlogn)O(nqlogn)。
60分算法:
考虑离线莫队。发现每次区间转移相当于删除/加入log个质数,最后询问是询问每个质数的最大的幂,可以用平衡树来维护,复杂度O(nn√log2n)O(n \sqrt n \log^2 n)。
100分算法:
考虑把一个数拆成多个质数相乘,若有一个因子是pkp^k,则拆成k个数,分别为p1,p2...pkp^1,p^2...p^k,每个数的权值都为p。这样转化成询问区间内不同的数的权值的乘积。
正确性:px!=py (x!=y)p^x!=p^y \ (x != y),若区间内同时出现两个数都有p的因子,则幂高的把幂低的覆盖掉了,每次都是统计的幂最高的数的贡献。
转化的问题可以离线+树状数组求解。
做法:
对于一个数x,记它上一次出现的位置为last[x],x的权值是val[x]。
离线操作是按右端点排序,然后左端点只负责询问,右端点的右移是不断加点的过程。
考虑前缀的区间减法,这样就能树状数组了。
每次加入一个数x,则要让last[x]=last[x]∗1/val[x]last[x]=last[x]*1/val[x],当前位置乘val[x]。支持的查询操作是查询前缀的乘积,然后求个逆元就行了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;typedef long long LL;
const int SZ = 3000010;
const int INF = 1000000010;
const int mod = 1000000007;int tot = 0,cnt = 0;
struct squ{int id,num,val,last;
}a[SZ];struct que{int l,r,id;LL ans;
}ask[SZ];bool cmp(que a,que b) { return a.r < b.r; }
bool cmp2(que a,que b) { return a.id < b.id; }map<int,int> mp; //分配种类 namespace init{bool vis[SZ];int pri[SZ];void gen(int n){vis[1] = 1;for(int i = 2,tot = 0;i <= n;i ++){if(!vis[i]) pri[++ tot] = i;for(int j = 1,m;j <= tot && (m = i * pri[j]) <= n;j ++){vis[m] = 1;if(i % pri[j] == 0) break;}}}void fj(int x,int id){for(int i = 1;(LL)pri[i] * pri[i] <= x;i ++){int t = 1;while(x % pri[i] == 0){t = t * pri[i];if(!mp[t]) mp[t] = ++ cnt;a[++ tot] = (squ){id,mp[t],pri[i],0};x /= pri[i];}}if(x != 1){if(!mp[x]) mp[x] = ++ cnt;a[++ tot] = (squ){id,mp[x],x,0};}}
}LL sum[SZ];
int n,m;void mult(int x,int d)
{if(x == 0) return ;for(int i = x;i <= n;i += i & -i)sum[i] = (LL)sum[i] * d % mod;
}int ask_ans(int x)
{int ans = 1;for(int i = x;i > 0;i -= i & -i)ans = (LL)ans * sum[i] % mod;return ans;
}LL ksm(LL a,LL b)
{LL ans = 1;while(b){if(b & 1) ans = (LL)ans * a % mod;a = (LL)a * a % mod;b >>= 1;}return ans;
}int ni(int x)
{return ksm(x,mod - 2);
}int last[SZ];int main()
{scanf("%d%d",&n,&m);init :: gen(100000);for(int i = 1,x;i <= n;i ++)scanf("%d",&x),init :: fj(x,i);for(int i = 1;i <= n;i ++)sum[i] = 1;for(int i = 1;i <= tot;i ++)a[i].last = last[a[i].num],last[a[i].num] = a[i].id;for(int i = 1;i <= m;i ++)scanf("%d%d",&ask[i].l,&ask[i].r),ask[i].id = i;sort(ask + 1,ask + 1 + m,cmp);for(int i = 1,j = 1,k = 1;i <= n;i ++){while(j <= tot && a[j].id == i)mult(i,a[j].val),mult(a[j].last,ni(a[j].val)),j ++;while(k <= m && ask[k].r == i)ask[k].ans = (LL)ask_ans(ask[k].r) * ni(ask_ans(ask[k].l - 1)) % mod,k ++;}sort(ask + 1,ask + 1 + m,cmp2);for(int i = 1;i <= m;i ++)printf("%lld\n",ask[i].ans);return 0;
}
【TsinsenA1339】JZPLCM(顾昱洲) 树状数组相关推荐
- 差分+树状数组 线段树【P2357】 守墓人
题目描述-->p2357 守墓人 敲了一遍线段树,水过. 树状数组分析 主要思路: 差分 简单介绍一下差分(详细概念太麻烦,看下面. 给定一个数组 7 8 6 5 1 8 18 20 35 // ...
- 洛谷 P5057 [CQOI2006]简单题(树状数组)
嗯... 题目链接:https://www.luogu.org/problem/P5057 首先发现这道题中只有0和1,所以肯定与二进制有关.然后发现这道题需要支持区间更改和单点查询操作,所以首先想到 ...
- Color the ball(HDU1556)树状数组
每次对区间内气球进行一次染色,求n次操作后后所有气球染色次数. 树状数组,上下区间更新都可以,差别不大. 1.对于[x,y]区间,对第x-1位减1,第y位加1,之后向上统计 #include<b ...
- 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组
[BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...
- Codeforces 629D Babaei and Birthday Cake(树状数组优化dp)
题意: 线段树做法 分析: 因为每次都是在当前位置的前缀区间查询最大值,所以可以直接用树状数组优化.比线段树快了12ms~ 代码: #include<cstdio> #include< ...
- poj_3067 树状数组
题目大意 左右两个竖排,左边竖排有N个点,从上到下依次标记为1,2,...N; 右边竖排有M个点,从上到下依次标记为1,2....M.现在从K条直线分别连接左边一个点和右边一个点,求这K条直线的交点个 ...
- hdu 1166 敌兵布阵(树状数组)
题意:区间和 思路:树状数组 #include<iostream> #include<stdio.h> #include<string.h> using names ...
- Equalizing Two Strings 冒泡排序or树状数组
首先考虑排序后相等 如果排序后相等的话就只考虑reverse长度为2的,所以a或者b排序后存在相邻两个字母相等的话就puts YES,n>26也直接puts YES 不然的话就假设c为a,b排完 ...
- Hdu 6534 Chika and Friendly Pairs 莫队算法+树状数组
题目链接 题意求给区间[L,R]中有少对(i,j)满足i<j且abs(a[i]-a[j])<=k. 首先来说暴力的方法就是离散化,然后用树状数组来维护,但是m次询问,m很大,所以说一定会t ...
- HDU - 5877 Weak Pair 2016 ACM/ICPC 大连网络赛 J题 dfs+树状数组+离散化
题目链接 You are given a rootedrooted tree of NN nodes, labeled from 1 to NN. To the iith node a non-neg ...
最新文章
- linux c 环境变量函数 getenv putenv 简介
- MySQL Workbench 怎么创建数据库
- G面经prepare: Set Intersection Set Difference
- 差动机器人毕业设计_双轮差动机器人曲线算法设计与实现
- C语言string.h文件函数汇总详解
- HTML5 上传图片预览
- glClearDepth
- linux grep 匹配空格_17 个案例,5 分钟简单搞定 Linux 正则表达式!
- 统计app用户在线时长_「云工作普及系列」2.如何实时统计工作时长,提高工作效率
- Nacos Spring Boot 快速开始
- 贴吧备份到本地浏览html,获取贴吧对应页html及写入文件
- 南昌大学计算机接收调剂的条件,关于2018年河南昌大学学硕士研究生接收调剂程序及要求的须知详情...
- Spring AOP异常处理(error at ::0 formal unbound in pointcut)
- 前端设备通过Ehome协议接入EasyCVR平台无法播放问题解决
- 架构篇--系统监控--spring-boot2.0.X 系统原生信息监控,SQL信息监控,cpu温度监控报警,cup磁盘内存使用率监控报警,自定义端点监控以及子节点获取,系统异常邮件通知
- 2021-08-23
- 简单二阶有源滤波电路分析
- 6种php加密解密方法
- 公共基础知识中计算机知识,公共基础知识之计算机知识总结
- 阿齐索-对接淘宝第三方平台
热门文章
- 全国各省会城市经纬度(包含港澳台)
- anki android 导入路径,3.1 导入卡片
- 真正的落雷(打印图形练习题)C语言
- 《计算机组成原理》作业,《计算机组成原理》作业一解答.doc
- excel如何隔行填充颜色
- python能做什么工作好-python可以做什么工作
- 各大云服务厂商 轻量应用服务器 性能评测对比,阿里云、腾讯云、华为云、Ucloud
- 腾讯QQ会员技术团队:人人都可以做深度学习应用:入门篇(下)
- nacos 2.0 Scanner SubTypesScanner was not configured
- 饭店流量预测-多表关联+lightgbm