知道对于一个数列,如果以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. LINQ to Entities 不支持 LINQ 表达式节点类型“Invoke”(笔记)

    今天使用使用动态查询的时候出现出现错误“LINQ to Entities 不支持 LINQ 表达式节点类型‘Invoke’.”,代码如下: IQueryable<CUSTOMER> que ...

  2. ssh下:系统初始化实现ServletContextListener接口时,获取spring中数据层对象无效的问题

    想要实现的功能:SSH环境下,数据层都交由Spring管理:在服务启动时,将数据库中的一些数据加载到ServletContext中缓存起来. 系统初始化类需要实现两个接口: ServletContex ...

  3. 0511Scrum项目3.0

    一.product backlog ID name Imp Est how to demo notes 1 主界面 3  3 用来登陆,离开,设置,关于按钮   2 算术界面 5 10 先用背景图来装 ...

  4. android单选框和复选框(练习)

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  5. IT公司100题-32-交换元素,使数组差最小

    问题描述: 有两个整数序列a, b,大小都为n, 序列元素的值任意整数,无序. 要求:通过交换a, b 中的元素,使得sum(a)-sum(b),差最小. 例如: var a=[80, 40, 60, ...

  6. JQuery特效分享网站

    各种jquery特效分享,可以去上面找资源. http://www.jqshare.com/

  7. iOS学习之NSPredictae及搜索框的实现

    NSPredicate Predicate 即谓词逻辑, Cocoa框架中的NSPredicate用于查询,作用是从数据堆中根据条件进行筛选.计算谓词之后返回的结果永远为BOOL类型的值,当程序使用谓 ...

  8. js中退出语句break,continue和return 比较 (转载)

    在 break,continue和return 三个关键字中, break,continue是一起的,return 是函数返回语句,但是返回的同时也将函数停止 首先:break和continue两个一 ...

  9. [Java Basics] multi-threading

    1, Process&Threads Most implementations of the Java virtual machine run as a single process. Thr ...

  10. 电子词典的相关子函数db.c程序

    整个电子词典是分块做的:包含的Dic_Server.c,Dic_Client.c,db.c,query.c,xprtcl.c,dict.h,xprtcl.h,dict.txt(单词文件) 下面是db. ...