hdu 5381 The sum of gcd
知道对于一个数列,如果以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的更多相关文章
- hdu 5381 The sum of gcd(线段树+gcd)
题目链接:hdu 5381 The sum of gcd 将查询离线处理,依照r排序,然后从左向右处理每一个A[i],碰到查询时处理.用线段树维护.每一个节点表示从[l,i]中以l为起始的区间gcd总 ...
- 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 ...
- 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 ...
- 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 ...
- HDU 5381 The sum of gcd (技巧,莫队算法)
题意:有一个含n个元素的序列,接下来有q个询问区间,对每个询问区间输出其 f(L,R) 值. 思路: 天真单纯地以为是道超级水题,不管多少个询问,计算量顶多就是O(n2) ,就是暴力穷举每个区间,再直 ...
- 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 ...
- HDOJ 5381 The sum of gcd 莫队算法
大神题解: http://blog.csdn.net/u014800748/article/details/47680899 The sum of gcd Time Limit: 2000/1000 ...
- 【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= ...
- hdu 4676 Sum Of Gcd 莫队+phi反演
Sum Of Gcd 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4676 Description Given you a sequence of ...
随机推荐
- Intellij快捷键
- windows下上传文件到VWware的centos
1.使用Xsell 连接到centos虚拟机,可以在虚拟机使用终端查看ip地址,命令:ifconfig -a 2.远程Linux系统上需要安装lrzsz工具包 Xsell命令:yum install ...
- SQL Server存储过程Return、output参数及使用技巧
SQL Server目前正日益成为WindowNT操作系统上面最为重要的一种数据库管理系统,随着 SQL Server2000的推出,微软的这种数据库服务系统真正地实现了在WindowsNT/2000 ...
- terminator终端工具
terminator是个很好的终端程序,在Ubuntu Linux下安装如下: sudo apt-get install terminator 可在同一屏打开多个窗口:
- DeepLearning之路(一)逻辑回归
逻辑回归 1. 总述 逻辑回归来源于回归分析,用来解决分类问题,即预测值变为较少数量的离散值. 2. 基本概念 回归分析(Regression Analysis):存在一堆观测资料,希望获得数据内 ...
- JSON序列化和反序列化的实例
之前有项目中使用到了Json的序列化和反序列化,现在将使用的实例记录下来以备查阅.如有不妥,请指教. 代码的最终目的是得到一个符合 resultClass<List<rtnGetFindM ...
- php中json_encode UTF-8中文乱码问题
最近在接口代码当中用到过json_encode,在网上找到说json_encode编码设置为UTF-8中文就不会乱码,经验证这办法确实是有效果的,但是不知道为什么,代码在用过一段时间之后就不太管用了. ...
- a few changes of Android 5.0
1.Service Intent must be explicit Intent serviceIntent = new Intent(context,MyService.class);context ...
- 鼠标点击页面任意标签,alert该标签名称(考虑兼容性)
<script type="text/JavaScript"> document.onclick=function(e){ e=e||window.event; ...
- SQL 变量
1.变量可以暂时储存数据 --定义变量: declare @xxx int --变量赋值: set @xxx=1 select @xxx=3 --变量的使用: print @xxx 2.--全 ...