知道对于一个数列,如果以x为左(右)端点,往右走,则最多会有log(a[x])个不同的gcd,并且有递减性

所以会分成log段,每一段的gcd相同

那我们可以预处理出对于每一个位置,以这个位置为左端点和右端点的时候,分别产生的gcd的值和分界处

那么这道题就可以用莫队算法了,O(n * sqrt(n) * logn)

标程是用线段树

代码:

  //File Name: hdu5381.cpp
//Author: long
//Mail: 736726758@qq.com
//Created Time: 2016年10月24日 星期一 11时36分49秒 #include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <vector>
#include <set>
#include <map>
#include <stdlib.h>
#define LL long long
#define pii pair<int,int>
#define fir first
#define sec second
#define mp make_pair
using namespace std;
const int MAXN = + ;
int bel[MAXN],a[MAXN],cur_l,cur_r,tot;
LL ans[MAXN],cur_ans;
vector<pii> tol[MAXN],tor[MAXN];
struct Query{
int l,r,t;
bool operator < (const Query & x) const{
if(bel[l] == bel[x.l]) return r < x.r;
return bel[l] < bel[x.l];
}
}que[MAXN];
int gcd(int x,int y){
return y == ? x : gcd(y, x % y);
}
void init(int n){
pii now;
for(int i=;i<=n;i++){
tol[i].clear();
tol[i].push_back(mp(i,a[i]));
if(i == ) continue;
int tot = ,len = tol[i-].size();
for(int j=;j<len;j++){
now = tol[i-][j];
int d = gcd(now.sec,a[i]);
if(d == tol[i][tot].sec)
tol[i][tot].fir = now.fir;
else{
tol[i].push_back(mp(now.fir,d));
tot++;
}
}
}
for(int i=n;i>;i--){
tor[i].clear();
tor[i].push_back(mp(i,a[i]));
if(i == n) continue;
int tot = ,len = tor[i+].size();
for(int j=;j<len;j++){
now = tor[i+][j];
int d = gcd(a[i],now.sec);
if(d == tor[i][tot].sec)
tor[i][tot].fir = now.fir;
else{
tor[i].push_back(mp(now.fir,d));
tot++;
}
}
}
}
LL gettol(int l,int r){
LL res = ;
int pre = r,len = tol[r].size();
for(int i=;i<len;i++){
pii now = tol[r][i];
if(l < now.fir){
res += (LL)(pre - now.fir + ) * now.sec;
pre = now.fir - ;
}
else{
res += (LL)(pre - l + ) * now.sec;
break;
}
}
return res;
}
LL gettor(int l,int r){
LL res = ;
int pre = l,len = tor[l].size();
for(int i=;i<len;i++){
pii now = tor[l][i];
if(r > now.fir){
res += (LL)(now.fir - pre + ) * now.sec;
pre = now.fir + ;
}
else{
res += (LL)(r - pre + ) * now.sec;
break;
}
}
return res;
}
void mover(int to){
while(cur_r < to){
cur_r++;
cur_ans += gettol(cur_l,cur_r);
}
while(cur_r > to){
cur_ans -= gettol(cur_l,cur_r);
cur_r--;
}
}
void movel(int to){
while(cur_l < to){
cur_ans -= gettor(cur_l,cur_r);
cur_l++;
}
while(cur_l > to){
cur_l--;
cur_ans += gettor(cur_l,cur_r);
}
}
void solve(int n,int q){
init(n);
int block = (int)sqrt(n + 0.5);
for(int i=;i<=n;i++)
bel[i] = (n - ) / block + ;
sort(que+,que+q+);
cur_l = cur_r = ,cur_ans = a[];
for(int i=;i<=q;i++){
mover(que[i].r);
movel(que[i].l);
ans[que[i].t] = cur_ans;
}
for(int i=;i<=q;i++)
printf("%I64d\n",ans[i]);
}
int main(){
int t,n,q;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",a + i);
scanf("%d",&q);
for(int i=;i<=q;i++){
scanf("%d %d",&que[i].l,&que[i].r);
que[i].t = i;
}
solve(n,q);
}
return ;
}

hdu 5381 The sum of gcd的更多相关文章

  1. hdu 5381 The sum of gcd(线段树+gcd)

    题目链接:hdu 5381 The sum of gcd 将查询离线处理,依照r排序,然后从左向右处理每一个A[i],碰到查询时处理.用线段树维护.每一个节点表示从[l,i]中以l为起始的区间gcd总 ...

  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 5381 The sum of gcd 2015多校联合训练赛#8莫队算法

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

  4. 2015 Multi-University Training Contest 8 hdu 5381 The sum of gcd

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

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

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

  6. HDU - 4676 :Sum Of Gcd (莫队&区间gcd公式)

    Given you a sequence of number a 1, a 2, ..., a n, which is a permutation of 1...n. You need to answ ...

  7. HDOJ 5381 The sum of gcd 莫队算法

    大神题解: http://blog.csdn.net/u014800748/article/details/47680899 The sum of gcd Time Limit: 2000/1000 ...

  8. 【HDU 5381】 The sum of gcd (子区间的xx和,离线)

    [题目] The sum of gcd Problem Description You have an array A,the length of A is nLet f(l,r)=∑ri=l∑rj= ...

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

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

随机推荐

  1. C#/ASP.NET MVC微信公众号接口开发之从零开发(一) 接入微信公众平台

    微信公众平台接入:其实很简单,把两个参数(地址和token)填入微信公众平台后台,暂时选择明文模式 ,其中token自己定义.微信服务器会根据后台填写的地址访问,并且带上对于的参数 如 url+&am ...

  2. iOS开发UI篇—使用picker View控件完成一个简单的选餐应用

    iOS开发UI篇—使用picker View控件完成一个简单的选餐应用 一.实现效果 说明:点击随机按钮,能够自动选取,下方数据自动刷新. 二.实现思路 1.picker view的有默认高度为162 ...

  3. HTML5新增Canvas标签及对应属性、API详解(基础一)

    知识说明: HTML5新增的canvas标签,通过创建画布,在画布上创建任何想要的形状,下面将canvas的API以及属性做一个整理,并且附上时钟的示例,便于后期复习学习!Fighting! 一.标签 ...

  4. nodejs 安装配置 for ubuntu

    安装nodejs sudo apt-get update sudo apt-get install nodejs -g  #全局安装 安装npm sudo apt-get install npm #查 ...

  5. cocos2dx 3.0 之 lua 创建类 (二)

    利用lua 中的table 特性 Base = {x = 0,y = 0} Base.name = "luohai"Base.age = 12Base.sex = "ma ...

  6. 【Avalon源码】iterator

    function iterator(vars, body, ret) { var fun = 'for(var ' + vars + 'i=0,n = this.length; i < n; i ...

  7. 2015GitWebRTC编译实录12

    2015.07.20 libjingle_peerconnection 编译通过[1382/1600 ] CXX obj/talk/app /webrtc/libjingle_peerconnecti ...

  8. HDU 4465 数值计算,避免溢出

    数学,数值计算,求期望 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4465题目描述:有两个盒子,每个中有n个糖果,(n<10^5)每次任选一 ...

  9. CF 628B New Skateboard --- 水题

    CD 628B 题目大意:给定一个数字(<=3*10^5),判断其能被4整除的连续子串有多少个 解题思路:注意一个整除4的性质: 若bc能被4整除,则a1a2a3a4...anbc也一定能被4整 ...

  10. poj3114 强连通+最短路

    题意:有 n 个城市,城市之间能够通过邮件或者电子邮件传递消息,已知 m 条邮件线路,每条线路代表 A 能送邮件到 B,并且花费 V 时间,如果几个城市之间能够相互邮件送达,那么他们就在同一个国家内, ...