hdu 5381 莫队算法/gcd

HDU 5381 The sum of gcd (2015年多校比赛第8场) 1.题目描述:点击打开链接 2.解题思路:本题利用莫队算法解决。由于是第一次学习这个算法,因此研究了比较长的一段时间才弄懂。首先,莫队算法解决的问题是无修改的离线区间查询问题。该算法实际上是由曼哈顿距离最小生成树演变来的,由于要处理m个区间,可以将这m个区间看做二维平面上的点,那么处理这m个区间就等价于让这m点连通,且总的转移代价最小。这其实就是一个曼哈顿距离最小生成树问题。 经典的曼 阅读详情

The sum of gcd

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 645    Accepted Submission(s): 279


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
 


 
区间查询问题,考虑离线的做法。这题关键点是,假如已知k个数a1,...,ak的gcd,那么在原来k个数基础上加多一个数,也就是a1,...ak+1,k+1个数的gcd,要么不变,要么就是至少少了一个因数,而最小的因数就是2,相当于至少变为原来的一半。也就是说1-n个数的gcd最多变了logn次。那么到以第i个数结尾的gcd前面最多可以分为logn段,每一段内gcd相同。有了这个能在logn时间内求出第i个数对前面任意以i结尾的区间的答案的贡献。也是就是知道了[l,r],能在logn内知道[l,r+1]和[l,r-1]。这个时候就可以用莫队算法了。

在网上找了很多莫队算法的资料,感觉就这个最好懂Mo's algorithm  

这场多校是中学生出的。。。应该是之前中学生被人抱怨出题太难,所以这题数据范围放小了,常数小的O(n^2)算法就能800ms水过。。(每次处理出第r个数的logn段gcd区间直接向前遍历一遍更新所有[i,r]的答案),莫队算法只用180ms


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
typedef pair<int, int> P;
typedef long long LL;
#define fir first
#define sec second
const int maxn=1e5+10;

int n,m,a[maxn];
int siz,num;

struct Query
{
    int l, r, id;
    int st;
    bool operator < (const Query& a) const
    {
        return st!=a.st ? st<a.st : r<a.r;
    }
};

Query q[maxn];
vector<P> seg[maxn], segr[maxn];

int gcd(int a, int b)
{
    int tmp;
    while(b){
        tmp=a%b;
        a=b;
        b=tmp;
    }
    return a;
}

LL ans[maxn];

int main()
{
    int t;
    cin>>t;
    while(t--){
        cin>>n;
        for(int i=0; i<=n; i++) seg[i].clear(), segr[i].clear();
        for(int i=0; i<n; i++) scanf("%d", a+i);
        siz=sqrt(n);
        num=(n+siz-1)/siz;

        cin>>m;
        for(int i=0; i<m; i++){
            scanf("%d%d", &q[i].l, &q[i].r);
            q[i].l--; q[i].r--;
            q[i].id=i;
            q[i].st=q[i].l/siz;
        }
        sort(q, q+m);


        for(int i=0; i<n; i++){
            if(i)
            for(int j=0; j<seg[i-1].size(); j++){
                int v=gcd(seg[i-1][j].sec, a[i]);
                int tot=seg[i].size();
                if(tot && seg[i][tot-1].sec==v)
                    seg[i][tot-1].fir=seg[i-1][j].fir;
                else
                    seg[i].push_back(P(seg[i-1][j].fir, v));
            }
            int tot=seg[i].size();
            if(tot && seg[i][tot-1].sec==a[i])
                seg[i][tot-1].fir=i;
            else seg[i].push_back(P(i, a[i]));
        }

        for(int i=n-1; i>=0; i--){
            for(int j=0; j<segr[i+1].size(); j++){
                int v=gcd(segr[i+1][j].sec, a[i]);
                int tot=segr[i].size();
                if(tot && segr[i][tot-1].sec==v)
                    segr[i][tot-1].fir=segr[i+1][j].fir;
                else
                    segr[i].push_back(P(segr[i+1][j].fir, v));
            }
            int tot=segr[i].size();
            if(tot && segr[i][tot-1].sec==a[i])
                segr[i][tot-1].fir=i;
            else segr[i].push_back(P(i, a[i]));
        }

        int l=0,r=0;
        LL val=a[0];
        for(int i=0; i<m; i++){
            while(r<q[i].r){
                r++;
                for(int j=seg[r].size()-1; j>=0; j--){
                    if(j &&l<=seg[r][j-1].first){
                        val+=(LL)seg[r][j].sec*(seg[r][j].fir-seg[r][j-1].fir);
                    }
                    else{
                        val+=(LL)seg[r][j].sec*(seg[r][j].fir-l+1);
                        break;
                    }
                }
            }

            while(r>q[i].r){
                for(int j=seg[r].size()-1; j>=0; j--){
                    if(j &&l<=seg[r][j-1].fir){
                        val-=(LL)seg[r][j].sec*(seg[r][j].fir-seg[r][j-1].fir);
                    }
                    else{
                        val-=(LL)seg[r][j].sec*(seg[r][j].fir-l+1);
                        break;
                    }
                }
                r--;
            }

            while(l<q[i].l){
                for(int j=segr[l].size()-1; j>=0; j--){
                    if(j &&r>=segr[l][j-1].fir){
                        val-=(LL)segr[l][j].sec*(segr[l][j-1].fir-segr[l][j].fir);
                    }
                    else{
                        val-=(LL)segr[l][j].sec*(r-segr[l][j].fir+1);
                        break;
                    }
                }
                l++;
            }

            while(l>q[i].l){
                l--;
                for(int j=segr[l].size()-1; j>=0; j--){
                    if(j &&r>=segr[l][j-1].fir){
                        val+=(LL)segr[l][j].sec*(segr[l][j-1].fir-segr[l][j].fir);
                    }
                    else{
                        val+=(LL)segr[l][j].sec*(r-segr[l][j].fir+1);
                        break;
                    }
                }
            }
            ans[q[i].id]=val;

        }

        for(int i=0; i<m; i++)
            printf("%I64d\n", ans[i]);

    }
    return 0;
}





HDU 5381 The sum of gcd 询问区间内所有子区间的GCD和 [莫队算法] 预处理+莫队,需要抓住 gcd 的本质。 阅读详情

相关推荐

Java 开发打飞机小游戏(附完整源码)

上图 写在前面 技术源于分享,所以今天抽空把自己之前用java做过的小游戏整理贴出来给大家参考学习。java确实不适合写桌面应用,这里只是通过这个游戏让大家理解oop面向对象编程的过程,纯属娱乐。代码写的很简单,也很容易理解,并且注释写的很清楚了,还有问题,自己私下去补课学习。 完整代码 敌飞机 import java.util.Random; 敌飞机: 是飞行物,也是敌人 public class Airplane extends FlyingObject implements Enemy {

一只独孤的程序猿 1万+

HDU5381(莫队算法+ST维护)

解题思路:写了两个小时才写出来,代码能力还有待加强。这道题一开始使用ST表进行维护,用于查询区间范围内的gcd值。但是莫队算法移动一格还有很多区间gcd累加的,要是一个个加必定超时。但是我们可以看出在一定范围内有不少区间的gcd值是一样的,不必一个个数,所以用二分搜索的方式查找,复杂度为O(logn)。我一开始没有事先记录下vl和vr(相同节点),而是要用的时候再查询,这样,复杂度就变成O(log...

qq_39861441的博客 367

Plecs仿真进阶:半桥LLC谐振变换器从开环到闭环的实战解析

本文通过Plecs软件,详细解析了半桥LLC谐振变换器从开环模型搭建到闭环控制实现的完整仿真流程。文章深入探讨了谐振参数设置、关键波形解读,并重点分享了基于PI控制器的闭环调试实战经验与参数整定技巧,帮助工程师高效掌握这一高效拓扑的仿真与设计方法。

weixin_29231263的博客 278

hdu-5213(莫队算法)

莫队算法介绍: 莫队算法是离线处理一类区间不修改查询类问题的算法。就是如果你知道了[L,R]的答案。你可以在O(1)的时间下得到[L,R-1]和[L,R+1]和[L-1,R]和[L+1,R]的答案的话。就可以使用莫队算法。 莫队算法预先知道了所有的询问。可以合理的组织计算每个询问的顺序以此来降低复杂度。要知道我们算完[L,R]的答案后现在要算[L',R']的答案。由于可以在O(1)的时间下

AC之路 1078

在Ubuntu 20.04上,用EtherCAT Igh 1.6.2驱动高创BD3E伺服电机(附完整C代码)

本文详细介绍了在Ubuntu 20.04实时内核环境下,使用EtherCAT Igh 1.6.2主站驱动高创BD3E伺服电机的完整实现方案。从实时系统配置、伺服电机PDO映射到精确控制线程设计,提供了完整的C代码样例和实际项目中的调试技巧,帮助开发者实现工业自动化中的高精度运动控制。

weixin_30772105的博客 110

LLM 大模型学习必知必会系列(十一):大模型自动评估理论和实战以及大模型评估框架详解

LLM 大模型学习必知必会系列(十一):大模型自动评估理论和实战以及大模型评估框架详解

丨汀、的博客 3216

hdu 5381 莫队...

The sum of gcd Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 854    Accepted Submission(s): 363 Problem Description You have an a

' 泪 添 无 言's blog 552

【100%通过率】华为OD机试真题 C++ 实现【打印机队列】【2022.11 Q4 新题】

有5台打印机打印文件,每台打印机有自己的待打印队列。因为打印的文件内容有轻重缓急之分,所以队列中的文件有1~10不同的代先级,其中数字越大优先级越高。打印机会从自己的待打印队列中选择优先级最高的文件来打印。如果存在两个优先级一样的文件,则选择最早进入队列的那个文件。现在请你来模拟这5台打印机的打印过程。

MISAYAONE的博客 9946

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

前言: 主要最近在刷莫队的题,这题GCD的特性让我对莫队的使用也有了新的想法。给福利:神犇的一套莫队算法题 先撇开题目,光说裸的一个莫队算法,主要的复杂度就是n*sqrt(n)对吧,这里我忽略了一个左端点(增加/删除)或者右端点(增加/删除)的所带来的复杂度, 之前也遇到过卡这里的复杂度,但是是因为简单的long long计算多而造成了复杂度增大,从而转变一下。 回到这道题:给...

weixin_30823683的博客 225

kaggle学习笔记-餐厅数据挖掘

分析Zomato数据集的基本思想是为了公平地了解影响在班加罗尔不同地方建立不同类型餐厅的因素,每个餐厅的总评级,班加罗尔是这样一个城市,拥有超过12,000家餐厅,餐厅供应来自世界各地的菜肴。每天都有新的餐馆开业,这个行业还没有饱和,需求也在与日俱增。然而,尽管需求不断增加,新餐馆却很难与老牌餐馆竞争。大多数餐厅都供应同样的食物。班加罗尔是印度的IT之都。这里的大多数人主要依靠餐馆的食物,因为他们没有时间自己做饭。由于对餐馆的需求如此巨大,因此研究一个地方的人口统计学就变得很重要。

优快云XXCQ的博客 1862

2026年北京君正数字IC笔试试卷带答案

本文摘要:该文档是一份数字IC设计相关的考试试题,包含单选题、多选题、波形分析题和代码设计题。内容涵盖时序约束、半导体工艺、状态机设计、逻辑综合、异步FIFO设计等知识点。试题解析详细,重点考察数字电路基础、时序分析和Verilog代码实现能力。典型题目包括多周期路径设置、Moore/Mealy状态机区别、同步复位与异步复位特性、RISC-V架构特点等,并提供了异步FIFO的Verilog实现参考代码。(149字)

Open 112

HDU - 5145 莫队算法

题意:有n个女生,每个女生都属于一个教室,现在要访问这些女生,就要进入教室,每次进入一个教室只能访问该教室的一个女生,现在要问对于[L,R]之间的女生全部访问,一共有多少种不同的访问教室的方式?思路:仔细想一下,因为最后的方案按照教室的不同来划分,那就与教室内部的女生访问顺序没有关系,那么只要拿所有女生的访问的排列数除以每个教室女生的排列数即可。 区间查询问题,不涉及修改操作,而且区间改变一个单位

Bahuia的博客 519

002、搭建你的第一个Agent开发环境:Python与核心库安装

在上一篇《Agent智能体开发入门:概念、应用与前景》中,我们描绘了Agent智能体的宏伟蓝图,理解了其作为“数字员工”的巨大潜力。然而,许多开发者在迈出第一步时,常常被复杂的依赖、版本冲突和晦涩的配置所劝退,空有想法却无从下手。这种感觉就像拿到了一张藏宝图,却找不到出发的港口。本文正是你的“启航指南”。我们将彻底解决这个痛点,通过一个清晰、可复现的流程,为你搭建一个专为Agent开发量身定制的Python环境。一个纯净、隔离的Python虚拟环境,避免项目间的“依赖地狱”。一套经过验证的核心工具链。

G_RE_RE的博客 111

HDU5381 莫队 gcd 预处理

题目链接:HDU 5381 题意:给出N个数,M个询问,对于每个询问,有一组[L,R],输出这个区间内所有子区间的GCD和。 思路:看完题目不难想到莫队,本来转移的时候想着可以rmq套个二分,然而超时了… 看了下别人题解才发现可以先预处理. 至于为什么可以这样预处理.我们发现 gcdgcdgcd 发生变化的话其值至少除2,因此种类顶多就 lognlog nlogn 种,预处理时间复杂度也就 O(n...

qq_40728222的博客 232

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

hdu 5381 The sum of gcd 莫队算法+区间gcd

题意: 略 思路: 杰哥说这种题他都做烂了。。。。orz 对于每个a[i]值,我们处理出以a[i]为起点,分别往左边和往右边的gcd区间的情况(gcd区间个数不会超过log(a[i])个,简单解释就是gcd相同的可以合并,且随着区间扩大,若gcd值不同,则每次至少除以2)。 a[i+1]的gcd区间可以由a[i]的情况推出,遇到可以合并的区间(gcd相等)就合并掉。 例如 2 3

1089

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

HDU 5381 The sum of gcd 莫队暴力

链接 题解链接:http://www.cygmasot.com/index.php/2015/08/15/hdu_5381/ 题意: 给定n长的序列 下面n个数给出这个序列 m个询问 下面m行给出询问的区间。 对于一个询问,输出这个区间内的任意子段的gcd 和。 思路: 因为一个数的gcd只会不变或下降,下降一次至少减半,下降至多32次,所以处理出每个数连续相同的gcd的区间。 然后暴力跑莫队。 #pragma comment(linker, "/STACK:1

九野的博客 2636

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

HDU - 5381 The sum of gcd 莫队

HDU - 5381 首先我们可以观察出从一个点开始的连续gcd最多只有log个, 因为gcd每次最少除2, 然后我们暴力莫队转移就好啦。 #include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi...

131

hdu 5381 The sum of gcd 莫队 + DP

第一次用莫队A题。 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5381 #include #include #include #include #include #include #include #include #include using namespace std; const int MAXN = 10005;

NM的专栏 904

HDU 5381 The sum of gcd

The sum of gcd Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description You have an array A,the length of A is n Let f(l,r)=∑ri=l∑rj=igcd

JYZ's Blog 478

hdu 5381 The sum of gcd

题意: 对于每次查询,计算∑i=lr∑j=irgcd(ai,ai+1,…,aj)\sum_{i=l}^{r}\sum_{j=i}^{r}gcd(a_i, a_{i+1}, \dots, a_j) 想法: 首先需要对于每一个ii预处理出[i,i→n][i, i \to n]这些区间的gcdgcd情况,即gcd(a[i]),gcd(a[i],a[i+],…,gcd(a[i],a[i+1

qqspeed 2391

(预处理+莫队算法)HDU - 5381 The sum of gcd

题意: 一个长度为n的数列,m次查询L到R之间所有连续子序列的gcd之和。 分析: 很明显的莫队算法。 很明显发现了gcd是单调递减的,并且最多存在32个的性质。 想了很久,脑补了许多种方法来拉伸L和R,但是都有漏洞。 实际上,这道题还是比较复杂的。。 在思考的过程中,我没有充分利用gcd的递减性质。 这题其实这题有共通之处,至少在我的做法上是这样的。 可以发现,在R向...

dijieluan7764的博客 249

【HDU5381_多校第八场B】【莫队算法】区间GCD之和_分段预处理

#include<stdio.h> #include<iostream> #include<string.h> #include<ctype.h> #include<math.h> #include<map> #include<set> #include<vector> #include<queue> #include<functional> #include<string> #include<al

snowy_smile的博客 941

HDU 5381 The sum of gcd 莫队算法

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5381 题意:给定一个数组,每次询问给出l和r,求出  思路:看的大牛的代码,心累 #include #include #include #include #include #include #define debug() puts("here") using namespace std;

弱智就要多努力 830
上一篇: 主席树(可持久化线段树)入门专题
下一篇: SPOJ COT2 树上的莫队算法,树上区间查询
HuanTongH
博客等级 码龄12年 7粉丝 110原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值