HDU 5381 The sum of gcd
来源:互联网 发布:手机淘宝所在地怎么改 编辑:程序博客网 时间:2024/06/06 15:47
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
Letf(l,r)=∑ri=l∑rj=igcd(ai,ai+1....aj)
Let
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 integersn
Second line hasn integers Ai
Third line has one integersQ ,the number of questions
Next there are Q lines,each line has two integersl ,r
1≤T≤3
1≤n,Q≤104
1≤ai≤109
1≤l<r≤n
First line has one integers
Second line has
Third line has one integers
Next there are Q lines,each line has two integers
Output
For each question,you need to print f(l,r)
Sample Input
251 2 3 4 531 32 31 444 2 6 931 32 42 3
Sample Output
9616182310
预处理gcd变化情况+莫队算法
/*莫队算法 区间内所有区间GCD和处理出以某点为左、右端点的GCD变化然后暴力使用莫队更新区间答案*/#pragma comment(linker, "/STACK:1024000000,1024000000")#include <set>#include <map>#include <stack>#include <cmath>#include <queue>#include <cstdio>#include <bitset>#include <string>#include <vector>#include <iomanip>#include <cstring>#include <iostream>#include <algorithm>#include <functional>#define maxn 50500using namespace std;typedef long long ll;const int N = 10000 + 5;int n, m;int block;int a[N];ll ans[N];struct Node{ int L, R; int id; bool operator<(const Node&rhs)const { if (L / block == rhs.L / block) { return R < rhs.R; } return L / block < rhs.L / block; }} q[N];int gcd(int a, int b){ return (b == 0) ? a : gcd(b, a % b);}struct He{ int idx; ll g;};vector<He>vl[N], vr[N];void preDeal(){ for (int i = 1; i <= n; i++) { if (i == 1)vl[i].push_back(He{i, a[i]}); else { int curg = a[i]; //当前的GCD值 int L = i; //第一个左端点 for (auto&it : vl[i - 1]) //每次都以i-1为右端点的区间开始扩展,得到以i为右端点的区间 { int g = gcd(it.g, curg); if (g != curg) vl[i].push_back(He{L, curg}); curg = g, L = it.idx; //更新curg和L值,得到新的左端点L 和 以L为左端点,i为右端点的区间的GCD值 } vl[i].push_back(He{L, curg}); //最后一个区间 } } for (int i = n; i >= 1; i--) //用同样的方法处理以i为左端点的所有区间 { if (i == n)vr[i].push_back(He{i, a[i]}); else { int curg = a[i]; int R = i; for (auto&it : vr[i + 1]) { int g = gcd(it.g, curg); if (g != curg) vr[i].push_back(He{R, curg}); curg = g, R = it.idx; } vr[i].push_back(He{R, curg}); } }}ll calc(int type, int L, int R) //计算区间[L,R]的结果{ ll res = 0; if (!type) { int tr = R; //当前的右端点 for (auto&it : vl[R]) if (it.idx >= L) //如果当前区间的左端点>=L,则当前区间为[it.idx,tr] { //这里其实用到了GCD值的传递性: //如果L<L1<R,gcd([L,R])=g1,gcd([L1,R])=g2(g2≥g1),那么必有gcd([L,L1-1])=g1 res += (tr - it.idx + 1) * it.g; tr = it.idx - 1; //更新右端点 } else //如果当前区间的左端点<L,则应该被算入的区间为[L,tr],由于它是最后一个区间了,因此break { res += (tr - L + 1) * it.g; break; } } else //原理同上 { int tl = L; for (auto&it : vr[L]) if (it.idx <= R) { res += (it.idx - tl + 1) * it.g; tl = it.idx + 1; } else { res += (R - tl + 1) * it.g; break; } } return res;}void solve(){ for (int i = 1; i <= n; i++) { vl[i].clear(), vr[i].clear(); } block = sqrt(n); //块数 sort(q, q + m); preDeal(); int L = 1, R = 0;//从(1, 0)点开始转移,此时res = 0 ll res = 0; for (int i = 0; i < m; i++) { while (R < q[i].R) { R++;//向右右端点,然后计算[L,R]区间的结果,累加给res res += calc(0, L, R); } while (R > q[i].R) //向左移动右端点 { res -= calc(0, L, R); R--; } while (L > q[i].L) { L--; res += calc(1, L, R); } while (L < q[i].L) { res -= calc(1, L, R); L++; } ans[q[i].id] = res; //转移完毕。注意,res,L,R都不要清零 } for (int i = 0; i < m; i++) { printf("%I64d\n", ans[i]); }}int main(){ int T; scanf("%d", &T); while (T--) { scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); } scanf("%d", &m); for (int i = 0; i < m; i++) { scanf("%d%d", &q[i].L, &q[i].R); q[i].id = i; } solve(); } return 0;}
0 0
- HDU 5381 The sum of gcd
- hdu 5381 The sum of gcd
- hdu 5381 The sum of gcd
- HDU 5381The sum of gcd
- HDU 5381 The sum of gcd
- HDU 5381 The sum of gcd
- HDU 5381 The sum of gcd
- hdu 5381 The sum of gcd(线段树+gcd)
- hdu 5381 The sum of gcd 莫队 + DP
- HDU 5381 The sum of gcd 莫队暴力
- HDU 5381 The sum of gcd 离线处理+线段树
- hdu 5381 The sum of gcd(线段树)
- HDU 5381The sum of gcd 莫队算法
- hdu 5381 The sum of gcd 莫队算法+区间gcd
- HDU 5381(The sum of gcd-莫队算法解决区间段gcd的和)
- 莫队算法,gcd(The sum of gcd,HDU 5381)
- Sum Of Gcd HDU
- hdu 5381 The sum of gcd 2015多校联合训练赛#8莫队算法
- 九度OJ题目1440:Goldbach's Conjecture
- 流氓DHCP服务器内网攻击测试
- day25_netstore
- 解决高并发的常见策略
- 博客
- HDU 5381 The sum of gcd
- Spring框架学习(10):基于注解的方式配置Bean
- linux初学 unit13
- CSS实现三角形的方法之一--利用 border 属性实现三角形
- 大数据处理思路与mysql分区1
- 学生信息管理系统
- HDU1134 Game of Connections
- 第九单元练习题
- 函数linspace生成按等差形式排列的行向量