题意:http://acm.hdu.edu.cn/showproblem.php?pid=5381

思路:这个题属于没有修改的区间查询问题,可以用莫队算法来做。首先预处理出每个点以它为起点向左和向右连续一段的gcd发生变化的每个位置,不难发现对每个点A[i],这样的位置最多logA[i]个,这可以利用ST表用nlognlogA[i]的时间预处理,然后用二分+RMQ在nlogn的时间内得到。然后就是区间变化为1时的转移了,不难发现区间变化为1时,变化的答案仅仅是以变化的那一个点作为左端点或右端点的连续子串的gcd的和,而这个gcd最多logA[i]种,利用前面的预处理可以在logA[i]的时间内累加得到答案。总复杂度O(NlogNlogA[i]+N√NlogA[i])

  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; #define X first
#define Y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define copy(a, b) memcpy(a, b, sizeof(a)) typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull; //#ifndef ONLINE_JUDGE
void RI(vector<int>&a,int n){a.resize(n);for(int i=;i<n;i++)scanf("%d",&a[i]);}
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?:-;
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?:-;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
//#endif
template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);} const double PI = acos(-1.0);
const int INF = 1e9 + ;
const double EPS = 1e-8; /* -------------------------------------------------------------------------------- */ const int maxn = 1e4 + ; int gcd(int a, int b) {
return b? gcd(b, a % b) : a;
} struct ST {
int dp[maxn][];
int index[maxn];
void init_index() {
index[] = ;
for (int i = ; i < maxn; i ++) {
index[i] = index[i - ];
if (!(i & (i - ))) index[i] ++;
}
}
void init_gcd(int a[], int n) {
for (int i = ; i < n; i ++) dp[i][] = a[i];
for (int j = ; ( << j) <= n; j ++) {
for (int i = ; i + ( << j) - < n; i ++) {
dp[i][j] = gcd(dp[i][j - ], dp[i + ( << (j - ))][j - ]);
}
}
} int query_gcd(int L, int R) {
int p = index[R - L + ];
return gcd(dp[L][p], dp[R - ( << p) + ][p]);
}
};
ST st; int n, q, block;
int a[maxn];
vector<int> L[maxn], R[maxn];
pair<pii, int> b[maxn]; bool cmp(const pair<pii, int> &a, const pair<pii, int> &b) {
int lb = a.X.X / block, rb = b.X.X / block;
return lb == rb? a.X.Y < b.X.Y : lb < rb;
} void init() {
for (int i = ; i < n; i ++) {
L[i].clear();
R[i].clear();
}
for (int i = ; i < n; i ++) {
int u = i;
R[i].pb(i - );
while (u < n) {
int l = u, r = n - ;
while (l < r) {
int m = (l + r + ) >> ;
if (st.query_gcd(i, m) == st.query_gcd(i, u)) l = m;
else r = m - ;
}
u = l + ;
R[i].pb(l);
}
}
for (int i = ; i < n; i ++) {
int u = i;
L[i].pb(i + );
while (u >= ) {
int l = , r = u;
while (l < r) {
int m = (l + r) >> ;
if (st.query_gcd(m, i) == st.query_gcd(u, i)) r = m;
else l = m + ;
}
u = l - ;
L[i].pb(l);
}
}
} ll f(int l, int r) {
ll ans = ;
for (int i = ; i < R[l].size(); i ++) {
if (r <= R[l][i]) return ans + (ll)(r - R[l][i - ]) * st.query_gcd(l, r);
ans += (ll)(R[l][i] - R[l][i - ]) * st.query_gcd(l, R[l][i]);
}
} ll g(int l, int r) {
ll ans = ;
for (int i = ; i < L[r].size(); i ++) {
if (l >= L[r][i]) return ans + (ll)(L[r][i - ] - l) * st.query_gcd(l, r);
ans += (ll)(L[r][i - ] - L[r][i]) * st.query_gcd(L[r][i], r);
}
} int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
int T;
cin >> T;
st.init_index();
while (T --) {
cin >> n;
block = (int)sqrt(n + 0.1);
for (int i = ; i < n; i ++) {
scanf("%d", a + i);
}
st.init_gcd(a, n);
init();
cin >> q;
for (int i = ; i < q; i ++) {
scanf("%d%d", &b[i].X.X, &b[i].X.Y);
b[i].X.X --;
b[i].X.Y --;
b[i].Y = i;
}
sort(b, b + q, cmp);
vector<ll> ans(q);
ll lastans = a[];
int lastl = , lastr = ;
/** 注意区间变化的顺序,优先考虑扩大区间,保证任何时刻区间不为负 */
for (int i = ; i < q; i ++) {
while (lastl > b[i].X.X) {
lastl --;
lastans += f(lastl, lastr);
}
while (lastr < b[i].X.Y) {
lastr ++;
lastans += g(lastl, lastr);
}
while (lastl < b[i].X.X) {
lastans -= f(lastl, lastr);
lastl ++;
}
while (lastr > b[i].X.Y) {
lastans -= g(lastl, lastr);
lastr --;
}
ans[b[i].Y] = lastans;
}
for (int i = ; i < q; i ++) {
printf("%I64d\n", ans[i]);
}
}
return ;
}

hdu5381 The sum of gcd]莫队算法的更多相关文章

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

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

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

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

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

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

  4. 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 ...

  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. HDU5381【莫队算法+区间GCD特性】

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

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

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

  9. 【BZOJ】2038: [2009国家集训队]小Z的袜子(hose)(组合计数+概率+莫队算法+分块)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2038 学了下莫队,挺神的orzzzz 首先推公式的话很简单吧... 看的题解是从http://for ...

随机推荐

  1. Matlab学习-(4)

    1. 函数 1.1 原始方法 之前我调用函数的方法是,首先写好函数文件,然后保存,然后在主函数中调用.这种方法的不足在于会导致你的工作目录的文件太多,从而导致很乱.在网上找了一些解决方法. 1.2 本 ...

  2. 华为鲲鹏服务器安装 k3s+rancher

    华为鲲鹏服务器安装 k3s+rancher 华为鲲鹏服务器 华为鲲鹏服务器采用华为自研cpu ARMv8架构,提供 Windows 和多个Linux 系统,作为服务器使用我一直使用Centos系统(不 ...

  3. golang实现并发爬虫二(简单调度器)

    上篇文章当中实现了单任务版爬虫. 那么这篇文章就大概说下,如何在上一个版本中进行升级改造,使之成为一个多任务版本的爬虫.加快我们爬取的速度. 话不多说,先看图: 其实呢,实现方法就是加了一个sched ...

  4. Springboot:整合Mybaits和Druid【监控】(十一)

    MyBatis默认提供了一个数据库连接池PooledDataSource,在此我们使用阿里提供的Druid数据库连接池 项目下载:https://files.cnblogs.com/files/app ...

  5. Linux系统安装docker教程-CentOS7(完美教程)

     一.前言 最近有网友反应不在安装Linux 安装docker,为了方便大家更快的安装,以CentOS7安装为例,写了一篇比较简单的博客,让大家学习. 二.背景介绍 Linux,全称GNU/Linux ...

  6. Trie树-提高海量数据的模糊查询性能

    今天这篇文章源于上周在工作中解决的一个实际问题,它是个比较普遍的问题,无论做什么开发,估计都有遇到过.具体是这样的,我们有一份高校的名单(2657个),需要从海量的文章标题中找到包含这些高校的标题,其 ...

  7. fasttext 和pysparnn的安装

  8. TensorFlow-keras 100分类

    import os os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' from tensorflow.python.keras.datasets import cifa ...

  9. KVM虚拟化平台环境部署

    一:安装依赖包 二:配置网卡 三:配置环境 实验环境: KVM01   192.168.200.10 关闭防火墙及相关的安全机制 [root@KVM01 ~]# systemctl stop fire ...

  10. MFC之动态调用自己写的类库中的类的成员方法

    第一步:创建一个要调用的类库 如果是MFC程序使用,可以创建一个MFC的类库,不过依然可以创建一个win32类库.我所知道的,MFC的类库可以分为常规MFC DLL和MFC扩展DLL关于它们之间的区别 ...