HDU-4676 Sum Of Gcd

题意:给定一个1-N的全排列序列,N<=20000,有Q组询问,Q<=20000,每组询问给出左右区间[l, r],问区间内的任意两个数的gcd之和为多少?

分析:早几场多校做过一道题目是问任意区间的gcd最大值为多少。使用的离线加线段树的方法。这题的解题就需要一些数论知识知识了。对于任意一段区间,任意两个数的gcd值一定会是区间内某个数的因子,因此我们从因子出发,通过得到该区间内所有数的所有因子分别出现的次数,那么就有线索来求最终的答案了。例如区间内数为[3, 6, 9, 36, 72],那么找到因子3,其出现的次数为5次,记为<3, 5>同样的有<2, 3>, <4, 2>, <6, 3>, <8,1>, <9, 3>, <18, 2>, <36, 2>, <72, 1>,如果此时以为对任意一个因子的个数 t ,取C(2, t)就错了,且不说因子个数只有一个的数不能够成为公因子(例如<8, 1>, <72, 1>等),就算成为公因子也未必是最大的公因子(例如<18, 2>等)。实际在统计的过程中不采用组合数的方式,而采用观察单个数带来的影响的方式。考虑到已知数 A 的因子 d 在区间其他数中出现了 k 次,那么如果 d 是所有gcd(A, other)的值时,那么最终的结果加上k*d,但这是不一定的,且 d 的因子肯定也是 A 的因子,当枚举到 d 的因子 d' 时显然就不能够加了。当务之急是找到某种方式使得所有的因子都被统计又不会是结果增多,没错,容斥。不过这里的容斥有点不太一样,而是给每个因子一个容斥因子f(d)使得 k*f(d) + k*f(d') + k*f(d'') + ... + k*f(1) = k*d,这样如果 d 出现 k 次,那么其因子的因子等等就也会出现 k 次,而将他们都统计起来的最终结果就是等效于 k*d。可以证明f(d) = phi(d),后者为欧拉函数。其实也即是 n = sum{phi(d) , d|n}。有了这些结论之后,把20000之内的数全部求出因子,然后对询问区间做一个起点以sqrt(n)分块的排序(不这样会TLE)动态的更新到每一个区间,每次讲边界的数进行更新,求出答案。

一段关于分块算法时间复杂度的分析:http://blog.csdn.net/yang_7_46/article/details/9618637

时间复杂度分析:

排完序后,对于相邻的两个查询,left值之间的差最大为sqrt(n),则相邻两个查询左端点移动的次数<=sqrt(n),总共有t个查询,则复杂度为O(t*sqrt(n))。又对于相同块内的查询,right端点单调上升,每一块所有操作,右端点最多移动O(n)次,总块数位sqrt(n),则复杂度为O(sqrt(n)*n)。right和left的复杂度是独立的,因此总的时间复杂度为O(t*sqrt(n)  +  n*sqrt(n))。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std; typedef long long LL;
const int N = ;
int M;
struct Node{
int l, r, No;
bool operator < (const Node &t) const {
int a = l/M, b = t.l/M; // 计算出端点落在以sqrt(n)分块的哪一块
if (a != b) return a < b;
return r < t.r;
}
};
int n, seq[N];
Node q[N];
int phi[N];
vector<int>v[N];
int num[N];
LL ans[N]; void prepare() {
for (int i = ; i < N; ++i) {
for (int j = i; j < N; j += i) {
v[j].push_back(i);
}
} // 处理每个数的因子
for (int i = ; i < N; ++i) phi[i] = i;
for (int i = ; i < N; ++i) {
if (phi[i] == i) {// 说明 i 是一个质数
for (int j = i; j < N; j += i) {
phi[j] = phi[j]/i*(i-);
}
}
}
} LL modify(int x, int f) {
LL ret = ;
for (int i = ; i < (int)v[x].size(); ++i) {
const int &d = v[x][i];
if (f == -) ret += phi[d] * (--num[d]);
else ret += phi[d] * (num[d]++);
}
return ret;
} void solve() {
int Q;
scanf("%d", &Q);
memset(num, , sizeof (num));
for (int i = ; i <= Q; ++i) {
q[i].No = i;
scanf("%d %d", &q[i].l, &q[i].r);
}
M = (int)sqrt(n);
sort(q+, q++Q);
LL ret = ;
int lb = q[].l, rb = q[].r; // 首先处理出第一个边界
for (int i = lb; i <= rb; ++i) {
ret += modify(seq[i], +);
}
ans[q[].No] = ret;
for (int i = ; i <= Q; ++i) {
int L = q[i].l, R = q[i].r;
while (lb > L) ret += modify(seq[--lb], +); // 首先进行区间放大
while (rb < R) ret += modify(seq[++rb], +);
while (lb < L) ret -= modify(seq[lb++], -);
while (rb > R) ret -= modify(seq[rb--], -);
ans[q[i].No] = ret;
}
for (int i = ; i <= Q; ++i) {
printf("%I64d\n", ans[i]);
}
} int main() {
prepare();
int T, ca = ;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = ; i <= n; ++i) {
scanf("%d", &seq[i]);
}
printf("Case #%d:\n", ++ca);
solve();
}
return ;
}

2013 Multi-University Training Contest 8的更多相关文章

  1. Integer Partition(hdu4658)2013 Multi-University Training Contest 6 整数拆分二

    Integer Partition Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...

  2. Partition(hdu4651)2013 Multi-University Training Contest 5

    Partition Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  3. ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków

    ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków Problem A: Rubik’s Rect ...

  4. Partition(hdu4651)2013 Multi-University Training Contest 5----(整数拆分一)

    Partition Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  5. JSU 2013 Summer Individual Ranking Contest - 5

    JSU 2013 Summer Individual Ranking Contest - 5 密码:本套题选题权归JSU所有,需要密码请联系(http://blog.csdn.net/yew1eb). ...

  6. HDU4888 Redraw Beautiful Drawings(2014 Multi-University Training Contest 3)

    Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. HDU 2018 Multi-University Training Contest 3 Problem A. Ascending Rating 【单调队列优化】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6319 Problem A. Ascending Rating Time Limit: 10000/500 ...

  8. 2015 Multi-University Training Contest 8 hdu 5390 tree

    tree Time Limit: 8000ms Memory Limit: 262144KB This problem will be judged on HDU. Original ID: 5390 ...

  9. hdu 4946 2014 Multi-University Training Contest 8

    Area of Mushroom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  10. 2016 Multi-University Training Contest 2 D. Differencia

    Differencia Time Limit: 10000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tot ...

随机推荐

  1. Javascript Window Location

    window.location 对象在编写时可不使用 window 这个前缀. URL : 统一资源定位符 (Uniform Resource Locator) 说明: 完整的URL示例:scheme ...

  2. 打开开源项目总得.md文件

    google了一些: 78 Tools for Writing and Previewing Markdown  http://mashable.com/2013/06/24/markdown-too ...

  3. Linux C socket 编程之TCP

    推荐:http://www.cnblogs.com/tianshuai11/archive/2011/11/30/2477224.html

  4. [BIM]BIM中IDM介绍

    参考:http://blog.fang.com/25866228/10613454/articledetail.htm IDM的全称是Information Delivery Manual,信息交付手 ...

  5. preparedStatement和Statement 有什么不一样

    1. PreparedStatement接口继承Statement, PreparedStatement 实例包含已编译的 SQL 语句,所以其执行速度要快于 Statement 对象.    2.作 ...

  6. c#之xml

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.X ...

  7. 周赛-Expression 分类: 比赛 2015-08-02 09:35 3人阅读 评论(0) 收藏

    A. Expression time limit per test1 second memory limit per test256 megabytes inputstandard input out ...

  8. linux设备驱动编写_tasklet机制

    在编写设备驱动时, tasklet 机制是一种比较常见的机制,通常用于减少中断处理的时间,将本应该是在中断服务程序中完成的任务转化成软中断完成. 为了最大程度的避免中断处理时间过长而导致中断丢失,有时 ...

  9. 浅谈CSS样式png、gif、jpg图片优化的方法

    一.PNG.GIF.JPG图片对比 在我们进行图像优化技术前,需要学习有关的图片格式的一些技术细节,每个图形格式都有自己的优势和拖弱点,知道他们会使你得到更好的视觉质量和压缩品质. 网页图片优化是网页 ...

  10. UML的概念模型

    为 了理解UML,需要形成该语言的概念模型,这要求学习建模的3个要素:UML的基本构造块.支配这些构造块如何放在一起的规则和一些运用于整个UML的公 共机制.如果掌握了这些思想,就能够读懂UML模型, ...