大神题解:

http://blog.csdn.net/u014800748/article/details/47680899

The sum of gcd

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 526    Accepted Submission(s): 226

Problem Description
You have an array A,the
length of A is n

Let f(l,r)=∑ri=l∑rj=igcd(ai,ai+1....aj)
 
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

First line has one integers n

Second line has n integers Ai

Third line has one integers Q,the
number of questions

Next there are Q lines,each line has two integers l,r

1≤T≤3

1≤n,Q≤104

1≤ai≤109

1≤l<r≤n
 
Output
For each question,you need to print f(l,r)
 
Sample Input
2
5
1 2 3 4 5
3
1 3
2 3
1 4
4
4 2 6 9
3
1 3
2 4
2 3
 
Sample Output
9
6
16
18
23
10
 
Author
SXYZ
 
Source
 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector> using namespace std; const int maxn=10100;
typedef long long int LL; struct G
{
G(){}
G(int _id,LL _g):id(_id),g(_g){} int id;
LL g; void toString()
{
printf("id: %d g: %lld\n",id,g);
}
}; int n,a[maxn],Q;
vector<G> VL[maxn],VR[maxn];
struct Que
{
int L,R,id;
bool operator<(const Que& que) const
{
if(L!=que.L) return L<que.L;
return R<que.R;
}
}que[maxn]; void PreInit()
{
/// get Left Point
/// 以i为右端点,预处理出左边的段
for(int i=1;i<=n;i++)
{
VL[i].clear();
if(i==1)
{
VL[i].push_back(G(i,a[i]));
}
else
{
LL curg=a[i];int L=i;
for(auto &it : VL[i-1])
{
int g=__gcd(it.g,curg);
if(g!=curg) VL[i].push_back(G(L,curg));
curg=g; L=it.id;
}
VL[i].push_back(G(L,curg));
}
}
/// get Right Point
/// 以i为左端点,预处理出右边的段
for(int i=n;i>=1;i--)
{
VR[i].clear();
if(i==n)
{
VR[i].push_back(G(i,a[i]));
}
else
{
LL curg=a[i];int R=i;
for(auto &it : VR[i+1])
{
int g=__gcd(curg,it.g);
if(g!=curg) VR[i].push_back(G(R,curg));
curg=g; R=it.id;
}
VR[i].push_back(G(R,curg));
}
}
} /// 计算L,R之间的值
LL calu(int type,int L,int R)
{
LL ret=0;
if(type==0)
{
int tr=R;
for(auto &it : VL[R])
{
if(it.id>=L)
{
ret+=(tr-it.id+1)*it.g;
tr=it.id-1;
}
else
{
ret+=(tr-L+1)*it.g;
break;
}
}
}
else if(type==1)
{
int tr=L;
for(auto &it : VR[L])
{
if(it.id<=R)
{
ret+=(it.id-tr+1)*it.g;
tr=it.id+1;
}
else
{
ret+=(R-tr+1)*it.g;
break;
}
}
}
return ret;
} LL ans[maxn]; int main()
{
int T_T;
scanf("%d",&T_T);
while(T_T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",a+i);
PreInit(); scanf("%d",&Q);
for(int i=0,l,r;i<Q;i++)
{
scanf("%d%d",&l,&r);
que[i].L=l; que[i].R=r; que[i].id=i;
}
sort(que,que+Q); int L=1,R=0; LL ret=0;
for(int i=0;i<Q;i++)
{
while(R<que[i].R)
{
R++;
ret+=calu(0,L,R);
}
while(R>que[i].R)
{
ret-=calu(0,L,R);
R--;
}
while(L<que[i].L)
{
ret-=calu(1,L,R);
L++;
}
while(L>que[i].L)
{
L--;
ret+=calu(1,L,R);
}
ans[que[i].id]=ret;
} for(int i=0;i<Q;i++)
cout<<ans[i]<<endl;
}
return 0;
}

HDOJ 5381 The sum of gcd 莫队算法的更多相关文章

  1. hdu5381 The sum of gcd]莫队算法

    题意:http://acm.hdu.edu.cn/showproblem.php?pid=5381 思路:这个题属于没有修改的区间查询问题,可以用莫队算法来做.首先预处理出每个点以它为起点向左和向右连 ...

  2. hdu 5381 The sum of gcd 莫队+预处理

    The sum of gcd Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) P ...

  3. HDU-4676 Sum Of Gcd 莫队+欧拉函数

    题意:给定一个11~nn的全排列AA,若干个询问,每次询问给出一个区间[l,r][l,r],要求得出∑l≤i<j≤r  gcd(Ai,Aj)的值. 解法:这题似乎做的人不是很多,蒟蒻当然不会做只 ...

  4. Hdu5381-The sum of gcd(莫队)

    题意我就不说了   解析: 莫队,先预处理出以i为右端点的区间的gcd值,有一些连续的区间的gcd值是相同的,比如[j,i],[j+1,i],[j+2,i]的gcd值是相同的,我们可以把[j,j+2] ...

  5. hdu 4676 Sum Of Gcd 莫队+phi反演

    Sum Of Gcd 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4676 Description Given you a sequence of ...

  6. hdu 4676 Sum Of Gcd 莫队+数论

    题目链接 给n个数, m个询问, 每个询问给出[l, r], 问你对于任意i, j.gcd(a[i], a[j]) L <= i < j <= R的和. 假设两个数的公约数有b1, ...

  7. HDU 5381 The sum of gcd (技巧,莫队算法)

    题意:有一个含n个元素的序列,接下来有q个询问区间,对每个询问区间输出其 f(L,R) 值. 思路: 天真单纯地以为是道超级水题,不管多少个询问,计算量顶多就是O(n2) ,就是暴力穷举每个区间,再直 ...

  8. HDU5381【莫队算法+区间GCD特性】

    前言: 主要最近在刷莫队的题,这题GCD的特性让我对莫队的使用也有了新的想法.给福利:神犇的一套莫队算法题 先撇开题目,光说裸的一个莫队算法,主要的复杂度就是n*sqrt(n)对吧,这里我忽略了一个左 ...

  9. hdu 5381 The sum of gcd

    知道对于一个数列,如果以x为左(右)端点,往右走,则最多会有log(a[x])个不同的gcd,并且有递减性 所以会分成log段,每一段的gcd相同 那我们可以预处理出对于每一个位置,以这个位置为左端点 ...

随机推荐

  1. 深入理解python对象及属性

    类属性和实例属性首先来看看类属性和类实例的属性在python中如何存储,通过__dir__方法来查看对象的属性 >>> class Test(object): pass>> ...

  2. Python2和Python3除法

    Python2和Python3除法   Python2除法:/,//,% "/":整数相除,向下取整:浮点数相除,结果包含小数(类似1/2,想保留小数应该写成1.0/2或者1*1. ...

  3. AutoIt简单使用

    以上是自己在公司做培训的PPT首页,其实在线的中文参考文档很全面,很值得学习的.

  4. 洛谷——P4053 [JSOI2007]建筑抢修

    P4053 [JSOI2007]建筑抢修 小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是T部落的基地里已经有N个建筑设施受到了严重的 ...

  5. [Luogu] P1131 [ZJOI2007]时态同步

    题目描述 题目描述 小Q在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数字1,2,3…进行标号.电路板的各个节点由若干不相交的导线相连接,且对于电路板的任何 ...

  6. 小甲鱼python疑难点

    1.python生成器 2.while 1: num = input('请输入一个整数(输入Q结束程序):') if num != 'Q': num = int(num) print('十进制 -&g ...

  7. 学习Python一年,基础忘记了,看看面试题回忆回议,Python面试题No3

    这边有几个面试题,好棒 第1题:你如何管理不同版本的代码? git,svn两个都要说到,github,码云也要提及,面试官想要的就是版本管理工具,你只要选择一个你熟悉的,疯狂的说一通就可以了,最好说一 ...

  8. python 网络编程基础

    1. 内容回顾补充 [] [^] 带有特殊意义的元字符到字符组内大部分都会取消它的特殊意义. 会取消的: [()+*.] -[(-)] -的位置决定了它的意义,写在字符组的第一个位置/最后一个位置就表 ...

  9. ECNU 3263 丽娃河的狼人传说 (贪心)

    链接:http://acm.ecnu.edu.cn/problem/3263/ 题意: 从 1 到 n 的一条数轴.有 m 个区间至少要安装一定数量的路灯,路灯只能装在整数点上,有k盏路灯已经安装好  ...

  10. 字符串类String类的判断功能

    StringDemo.java /* * Object:是类层级结构中的根类,所有的类都直接或间接的继承自该类. * 如果一个方法的形式参数是Object,那么这里我们就可以传递它的任意的子类对象. ...