题意: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. 19.SpringCloud实战项目-SpringCloud整合Alibaba-Nacos配置中心

    SpringCloud实战项目全套学习教程连载中 PassJava 学习教程 简介 PassJava-Learning项目是PassJava(佳必过)项目的学习教程.对架构.业务.技术要点进行讲解. ...

  2. 详解 HashMap

    本篇博文的知识点,在我们的日常生活中,应用十分广阔.比如:每个学生,都有自己的对应的学号.每一个公民,都有自己的身份证号- - 相信看到这里,有的同学基本上已经猜到了这个类的主要用途.那么,话不多说, ...

  3. [转]PHP利用PCRE回溯次数限制绕过某些安全限制

    这次Code-Breaking Puzzles中我出了一道看似很简单的题目pcrewaf,将其代码简化如下: <?php function is_php($data){ return preg_ ...

  4. Spring Boot将Mybatis返回结果转为驼峰的三种实现方式

    本文不再更新,可能存在内容过时的情况,实时更新请访问原地址:Spring Boot将Mybatis返回结果转为驼峰的三种实现方式: 我们通常获取Mybatis返回的数据结果时想要将字段以驼峰的形式返回 ...

  5. 归并排序(归并排序求逆序对数)--16--归并排序--Leetcode面试题51.数组中的逆序对

    面试题51. 数组中的逆序对 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 示例 1: 输入: [7,5,6,4] 输出 ...

  6. 支付宝开源非侵入式 Android 自动化测试工具 Soloπ

    Soloπ(SoloPi)是支付宝开源的一个无线化.非侵入式的Android自动化测试工具,公测版拥有录制回放.性能测试.一机多控三项主要功能,能为测试开发人员节省宝贵时间. 本文是SoloPi团队关 ...

  7. es6最 全教程2020年

    带手机验证码登陆, 带全套购物车系统 带数据库 前后端分离开发 带定位用户功能 数据库代码为本地制作好了 带支付宝支付系统 带django开发服务器接口教程 地址:   https://www.dua ...

  8. spring-boot-lll-starter自动化框架介绍

    1. spring-boot-lll-starter自动化框架介绍 1.1. 前言 舔着脸来介绍一波我刚写的自动化框架,spring-boot-lll-starter框架是经由我企业实战总结的一套,适 ...

  9. Docker help详细帮助

    常用的 docker 命令 docker # docker 命令帮助 Commands: attach Attach to a running container # 当前 shell 下 attac ...

  10. chcp437 转换英语,在西班牙语系统中无效

    https://social.technet.microsoft.com/Forums/en-US/9c772011-5094-4df0-bf73-7140bf91673b/chcp-command- ...