题意: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. 详解PHP反序列化中的字符逃逸

    首发先知社区,https://xz.aliyun.com/t/6718/ PHP 反序列化字符逃逸 下述所有测试均在 php 7.1.13 nts 下完成 先说几个特性,PHP 在反序列化时,对类中不 ...

  2. [腾讯云]简单在腾讯云 CenTOS7.0 安装Nginx,Mysql(MariaDB),Memcache,解析PHP!

    1.安装LNMP之前要安装EPEL,以便安装源以外的软件,如Nginx,phpMyAdmin等. yum install epel-release 2.安装Nginx a) yum install n ...

  3. 如何将Python项目发布到PyPI

    The Python Package Index (PyPI) is a repository of software for the Python programming language. 如何打 ...

  4. Java代码生成器加入postgresql数据库、HikariCP连接池、swagger2支持!

    目录 前言 PostgreSql VS MySql HikariCP VS Druid Swagger2 自定义参数配置一览 结语 前言   最近几天又抽时间给代码生成器增加了几个新功能(预计今晚发布 ...

  5. 2019-2020-1 20199329《Linux内核原理与分析》第七周作业

    <Linux内核原理与分析>第七周作业 一.本周内容概述: 对Linux系统如何创建一个新进程进行追踪 分析Linux内核创建一个新进程的过程 二.本周学习内容: 1.学习进程的描述 操作 ...

  6. Redis持久化存储(一)

    Redis介绍 Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库. Redis 与其他 key - value 缓存产品有以下三个特点: Redis支持数据的持久化 ...

  7. Scala教程之:函数式的Scala

    文章目录 高阶函数 强制转换方法为函数 方法嵌套 多参数列表 样例类 比较 拷贝 模式匹配 密封类 单例对象 伴生对象 正则表达式模式 For表达式 Scala是一门函数式语言,接下来我们会讲一下几个 ...

  8. 【Linux网络基础】网络子网划分基础知识(IP地址,子网)

    一. IP地址分类与子网划分基础 1. 什么是IP地址? 常见的ip地址版本为ipv4, ipv6 32位 4 * 8=32位. 32位二进制数字序列组成的数字序列   点分十进制 采用点将32位数字 ...

  9. qemu-img 整理

    qemu-img命令语法: qemu-img command [command options] check命令: check [-f fmt < qcow2 | qed | vdi >] ...

  10. values/colors.xml

    <color name="abcd">#FFC4C4C4</color> <color name="white">#FFFF ...