【倍增】LCM QUERY
给一个序列,每次给一个长度l,问长度为l的区间中lcm最小的。


题解:因为ai<60,所以以某个点为左端点的区间的lcm只有最多60种的情况,而且相同的lcm区间的连续的。
所以就想到一个n*60*logn的做法,倍增找出每个点的区间lcm情况,然后修改答案……
1-60的lcm的积大于long long,只能把数拆开,然后比较时用log,结果才用这个数的质因数相乘。
问题在于一开始我对于每个点开个20的数组记录60内第几个质数的个数,这样每次常数就要再乘个20,然后就tle……
优化的方法是位运算,因为只会是2,3,5,7的次幂大于1次,单独记录,其他的只会是0次幂和1次幂。
最后作死的两个小错误:33不是质数……,用ln【60】数组记录log的值然而其中对n取对数……
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define maxn 40000
#define mm 1000000007
#define LL long long
#define inf 100000000000
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define dow(i,l,r) for(int i=r;i>=l;i--)
using namespace std; typedef struct {
int v1;
double v2;
}Big;
Big tree[maxn*];
double ln[maxn];
int f[maxn][],now;
int n,m,maxln,tot=;
LL ans1[maxn],ans2[maxn];
int pri[]={,,,,
,,,,
,,,,
,,,,
,,,,
,,,,}; double calc(int x)
{
double sum=;
rep(i,,tot)
if ((x>>i)&)
sum+=ln[pri[i]];
dow(i,,)
if ((x>>i)&) {
sum+=(i+)*ln[];
break;
}
if ((x>>)&) sum+=*ln[];
else
if ((x>>)&) sum+=*ln[];
else
if ((x>>)&) sum+=ln[]; if ((x>>)&) sum+=*ln[];
else
if ((x>>)&) sum+=ln[]; if ((x>>)&) sum+=*ln[];
else
if ((x>>)&) sum+=ln[]; return sum;
} LL answer(Big x)
{
LL sum=;
rep(i,,tot)
if ((x.v1>>i)&)
sum=sum*pri[i]%mm;
dow(i,,)
if ((x.v1>>i)&) {
sum=sum*pri[i]%mm;
break;
}
if ((x.v1>>)&) sum=sum*%mm;
else
if ((x.v1>>)&) sum=sum*%mm;
else
if ((x.v1>>)&) sum=sum*%mm; if ((x.v1>>)&) sum=sum*%mm;
else
if ((x.v1>>)&) sum=sum*%mm; if ((x.v1>>)&) sum=sum*%mm;
else
if ((x.v1>>)&) sum=sum*%mm; return sum;
} void build(int x,int l,int r)
{
tree[x].v2=inf;
if (l==r) return;
int mid=(l+r)>>;
build(x<<,l,mid);
build(x<<|,mid+,r);
} void change(int x,int l,int r,int ll,int rr,double z)
{
if (tree[x].v2<=z) return;
if (ll<=l && r<=rr) {
tree[x].v1=now;
tree[x].v2=z;
return;
}
int mid=(l+r)>>;
if (ll<=mid) change(x<<,l,mid,ll,rr,z);
if (rr>mid) change(x<<|,mid+,r,ll,rr,z);
} Big ask(int x,int l,int r,int y)
{
if (l==r) return tree[x];
int mid=(l+r)>>;
Big more;
if (y<=mid) more=ask(x<<,l,mid,y);
else more=ask(x<<|,mid+,r,y);
if (more.v2<tree[x].v2) return more;
return tree[x];
} int main()
{
rep(i,,maxn-) ln[i]=log(i);
int tt=;
while (scanf("%d %d",&n,&m)!=EOF) {
++tt;
rep(i,,n) {
f[i][]=;
int k;
scanf("%d",&k);
dow(j,,tot)
if (k%pri[j]==) k/=pri[j],f[i][]+=<<j;
}
maxln=floor(ln[n]/ln[])+;
rep(i,,maxln)
rep(j,,n+-(<<i))
f[j][i]=f[j][i-]|f[j+(<<(i-))][i-];
build(,,n);
rep(i,,n) {
int l=i;
now=;
while (l<=n) {
// printf("!!%d %d\n",now,f[l][0]);
now=now|f[l][];
int r=l;
dow(j,,maxln)
if (r-+(<<j)<=n && !(~((~f[r][j])|now)) ) r=r-+(<<j); change(,,n,l-i+,r-i+,calc(now));
l=r+;
}
} while (m--) {
int j;
scanf("%d",&j);
printf("%lld\n",answer(ask(,,n,j)));
}
}
return ;
}
这种区间答案连续的思想并不是第一次遇见了
【倍增】LCM QUERY的更多相关文章
- 刷题总结——Interval query(hdu4343倍增+贪心)
题目: Problem Description This is a very simple question. There are N intervals in number axis, and M ...
- QTREE2 spoj 913. Query on a tree II 经典的倍增思想
QTREE2 经典的倍增思想 题目: 给出一棵树,求: 1.两点之间距离. 2.从节点x到节点y最短路径上第k个节点的编号. 分析: 第一问的话,随便以一个节点为根,求得其他节点到根的距离,然后对于每 ...
- 【HDU 4343】Interval query(倍增)
BUPT2017 wintertraining(15) #8D 题意 给你x轴上的N个线段,M次查询,每次问你[l,r]区间里最多有多少个不相交的线段.(0<N, M<=100000) 限 ...
- [SPOJ913]QTREE2 - Query on a tree II【倍增LCA】
题目描述 [传送门] 题目大意 给一棵树,有两种操作: 求(u,v)路径的距离. 求以u为起点,v为终点的第k的节点. 分析 比较简单的倍增LCA模板题. 首先对于第一问,我们只需要预处理出根节点到各 ...
- HDU4343Interval query 倍增
去博客园看该题解 题意 给定n个区间[a,b),都是左闭右开,有m次询问,每次询问你最多可以从n个区间中选出多少[L,R]的子区间,使得他们互不相交. n,m<=10^5. 区间下标<=1 ...
- SPOJ375 Query on a tree 【倍增,在线】
题目链接[http://www.spoj.com/problems/QTREE/] 题意:给出一个包含N(N<=10000)节点的无根树,有多次询问,询问的方式有两种1.DIST a b 求a ...
- Query on a tree II 倍增LCA
You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, ...
- spoj 913 Query on a tree II (倍增lca)
Query on a tree II You are given a tree (an undirected acyclic connected graph) with N nodes, and ed ...
- HDU 4343 Interval query(贪心 + 倍增)
题目链接 2012多校5 Problem D 题意 给定$n$个区间,数字范围在$[0, 10^{9}]$之间,保证左端点严格大于右端点. 然后有$m$个询问,每个询问也为一个区间,数字范围在$[ ...
随机推荐
- Android7.0 应用内升级
Android7.0应用内升级 最近线上项目在7.0机器上出现应用内升级失败,原来是由于Android7.0权限问题导致. 如果项目的 targetSdkVersion>=24 在处理应用内升级 ...
- vim中project多标签和多窗口的使用
1.打开多个窗口 打开多个窗口的命令以下几个: 横向切割窗口 :new+窗口名(保存后就是文件名) :split+窗口名,也可以简写为:sp+窗口名 纵向切割窗口名 :vsplit+窗口名,也可以简写 ...
- ACID、数据库隔离级别
ACID: A(Atomicity):原子性,要么全部执行,要么都不执行 C(consistency):一致性: 特点: 1.一个操作除法级联,这些必须成功,否则全部失败(原子性) 2.所有节点同步更 ...
- 基于Python的接口自动化
第一步 Python的安装配置 打开官网: https://www.python.org/downloads/ 目前官网上已经更新到3.6.1啦,有两个版本,大家可以按自己喜欢的去下载,我自己选择的是 ...
- 流畅的python(笔记)
流畅的python中有很多奇技淫巧,整本书都在强调如何最大限度地利用Python 标准库.介绍了很多python的不常用的数据类型.操作.库等,对于入门python后想要提升对python的认识应该有 ...
- JAVA 面试须知
本篇文章会对面试中常遇到的Java技术点进行全面深入的总结,帮助我们在面试中更加得心应手,不参加面试的同学也能够借此机会梳理一下自己的知识体系,进行查漏补缺. 1. Java中的原始数据类型都有哪些, ...
- Ubuntu14.04下部署FastDFS 5.08+Nginx 1.9.14
最新的版本可以在这里获取,目前下载的最新版本是5.08,更新于2016-02-03.在这里可以找到更多的说明. 下载好后,server端分为两个部分,一个是tracker,一个是storage.顾 ...
- ACM 第五天
匈牙利算法(二分图匹配) C - Courses Consider a group of N students and P courses. Each student visits zero, one ...
- lintcode-42-最大子数组 II
42-最大子数组 II 给定一个整数数组,找出两个 不重叠 子数组使得它们的和最大. 每个子数组的数字在数组中的位置应该是连续的. 返回最大的和. 注意事项 子数组最少包含一个数 样例 给出数组 [1 ...
- LintCode-378.将二叉查找树转换成双链表
将二叉查找树转换成双链表 将一个二叉查找树按照中序遍历转换成双向链表. 样例 给定一个二叉查找树: 返回 1<->2<->3<->4<->5. 标签 链 ...