个人感觉题解的复杂度很玄,参不透,有没有大佬讲解一下- -

/*
HDU 6102 - GCDispower [ 数论,树状数组] | 2017 Multi-University Training Contest 6
题意:
给定排列 a[N], M 组 L,R
求解 ∑ [ L <= i < j < k <= R ] [ GCD(a[i], a[j]) == a[k] ] * a[k]
限制:N, M <= 1e5
分析:
数论角度一般考虑枚举 k,由于是区间询问,且贡献有可加性,考虑对每个L,将[L, R-1] 推到 [L, R]
故对于每一个R, 枚举 a[R] 倍数 a[i] (i < R)
再对每一个 a[i] , 求得满足 i < j < R && GCD(a[i], a[j]) == a[R] 的个数
即 GCD(a[i]/a[R], a[j]/a[R]) == 1 的个数
此时对于 L ∈ [1,i-1] 的区间,贡献 = 所得个数 * a[R] , 这部分用区间更新可以完成 求 GCD(a[i]/a[R], a[j]/a[R]) == 1 的 j 的个数,用容斥原理
a[j]是a[R]的倍数的总个数 - a[j]与a[i]不互质的个数
= a[j]是a[R]的倍数的总个数 - a[j] 是 a[i] 的 1个质因子之积的倍数的个数
+ a[j] 是 a[i] 的 2个质因子之积的倍数的个数
...
+ (-1)^k * a[j] 是 a[i] 的 k个质因子之积的倍数的个数
所以预处理每个数所有质因子之积,然后容斥的参数 μ = -1^(k) 可以用莫比乌斯函数
具体处理时,可以维护每个质因子之积的倍数,每处理一个 a[i] , 就将它的每个质因子之积的倍数个数+1 复杂度:
预处理 O(n+n^1.5)
枚举 R 和 a[i] 均摊 O(nlog(n)), 枚举 a[i] 的因子容斥 O(n^0.5)
区间查询,更新 O(log(n))
总复杂度 : O(n + n^1.5 + T * n * log(n)*(n^0.5 + log(n))) 不过由于枚举因子时枚举的是非完全平方数,不足n^0.5,可能优化下来就 n*log(n)^2 了(???)
*/
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 100005;
bool notp[N];
int prime[N], pnum, mu[N];
vector<int> fac[N];
void Mobius() {
memset(notp, 0, sizeof(notp));
mu[1] = 1;
for (int i = 2; i < N; i++) {
if (!notp[i]) prime[++pnum] = i, mu[i] = -1;
for (int j = 1; prime[j]*i < N; j++) {
notp[prime[j]*i] = 1;
if (i%prime[j] == 0) {
mu[prime[j]*i] = 0;
break;
}
mu[prime[j]*i] = -mu[i];
}
}
for (int i = 1; i < N; i++)
for (int j = 1; j*j <= i; j++) {
if (j*j == i && mu[j]) fac[i].push_back(j);
else if (i%j == 0) {
if (mu[j]) fac[i].push_back(j);
if (mu[i/j]) fac[i].push_back(i/j);
}
}
}
int t, n, m, a[N], vis[N];
struct Query {
int l, id;
};
vector<Query> Q[N];
LL ans[N];
LL c[N];
void modify(int x, int num) {
if (x == 0) return;
while (x <= n) c[x] += num, x += x&-x;
}
LL sum(int x){
LL s = 0;
while (x) s += c[x], x -= x&-x;
return s;
}
int cnt[N];
void addCnt(int x) {
for (auto& y : fac[x]) cnt[y]++;
}
void solve(int l, int x, int k)
{
int num = 0;
for (auto& y : fac[x])
num += mu[y] * cnt[y];
modify(1, k*num);
modify(l+1, -k*num);
addCnt(x);
}
vector<int> mul;
bool cmp(int a, int b) {
return a > b;
}
void init() {
memset(vis, 0, sizeof(vis));
memset(cnt, 0, sizeof(cnt));
memset(c, 0, sizeof(c));
for (int i = 0; i < N; i++) Q[i].clear();
}
int main()
{
Mobius();
scanf("%d", &t);
while (t--)
{
init();
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= m; i++)
{
int l, r; scanf("%d%d", &l, &r);
Q[r].push_back(Query{l, i});
}
for (int i = 1; i <= n; i++)
{
mul.clear();
for (int j = 2*a[i]; j <= n; j += a[i])
if (vis[j]) mul.push_back(vis[j]);
sort(mul.begin(), mul.end(), cmp);
for (auto & l : mul) solve(l, a[l]/a[i], a[i]);
for (int j = 0; j <= n/a[i]; j++) cnt[j] = 0;
vis[a[i]] = i;
for (auto& x : Q[i]) ans[x.id] = sum(x.l);
}
for (int i = 1; i <= m; i++) printf("%lld\n", ans[i]);
}
}

HDU 6102 - GCDispower | 2017 Multi-University Training Contest 6的更多相关文章

  1. hdu 4930 Fighting the Landlords--2014 Multi-University Training Contest 6

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4930 Fighting the Landlords Time Limit: 2000/1000 MS ...

  2. HDU 6168 - Numbers | 2017 ZJUT Multi-University Training 9

    /* HDU 6168 - Numbers [ 思维 ] | 2017 ZJUT Multi-University Training 9 题意: .... 分析: 全放入multiset 从小到大,慢 ...

  3. HDU 5726 GCD (2016 Multi-University Training Contest 1)

      Time Limit: 5000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Description Give y ...

  4. HDU 5360 Hiking(优先队列)2015 Multi-University Training Contest 6

    Hiking Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total S ...

  5. hdu 6394 Tree (2018 Multi-University Training Contest 7 1009) (树分块+倍增)

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=6394 思路:用dfs序处理下树,在用分块,我们只需要维护当前这个点要跳出这个块需要的步数和他跳出这个块去 ...

  6. hdu 6102 GCDispower

    多校6 GCDispower(容斥) 题意: 给一个长度为\(n\)的排列 给q组询问 每次查询\(L,R\)内的答案 \(\sum_{i=L}^{R}\sum_{j=i+1}^{R}\sum_{k= ...

  7. HDU 4951 Multiplication table(2014 Multi-University Training Contest 8)

    思路   如果进制为p    那么当x<p时 (p-1)*(p-x)=(p-(x+1))  *p +x     因为x<p  所以没有进位  所以高位上的数字为    p-(x+1). 根 ...

  8. HDU 4938 Seeing People(2014 Multi-University Training Contest 7)

    思路:根据出发时间把点往速度反方向移动 t*v的 的距离这样就可以当成 全部点一起出发,再把y轴上的点固定不动相当于x轴的点向(-v2,v1)方向移动 .可以把所有点映射到x轴上进行统计即可(要记住同 ...

  9. HDU 4937 Lucky Number(2014 Multi-University Training Contest 7)

    思路:先枚举  a*bas +b = n  求出 bas 在sqrt(n)到n的  (bas>a&&bas>b) 再枚举  a*bas*bas+b*bas+c =n  求出 ...

随机推荐

  1. mysql导入数据报错:Incorrect datetime value

    incorrect datetime value 报错信息如下图: 意思很明显是说,'0000-00-00 00:00:00'不是一个有效的日期类型的值 解决办法: sql_mode 中删除 NO_Z ...

  2. Hadoop介绍与安装

    前言 最近想学习下大数据,有点急于求成,于是去网上找了各种培训机构的视频,发现大都质量不佳,理论基本不说或者简单讲下,然后教你照猫画虎的敲代码,出了问题都没法分析.最后还是找了厦门大学的公开课从理论开 ...

  3. org.springframework.http.converter.HttpMessageNotReadableException

    发起请求报错:org.springframework.http.converter.HttpMessageNotReadableException 查看请求头: application/json 所以 ...

  4. javaweb关于用户是否登录全局判断,没有登录跳转到登录界面

    有这样一个需求,用户密码登录网站,在session中保留了用户的信息,但是用户很长时间没有再操作该界面,用户的session则被浏览器清除,而一些业务逻辑则是需要用到用户的信息,那么用户再执行操作后, ...

  5. ROS的初步学习--创建一个工作空间和一个程序包

    快速开始 创建工作区(workspace) 工作区可以作为一个独立的项目进行编译,存放ROS程序的源文件.编译文件和执行文件.建立工作区的方法如下: mkdir -p ~/catkin_ws/src ...

  6. Go-函数高级使用-条件分支-包管理-for循环-switch语句-数组及切片-与或非逻辑符

    目录 科普 python 注释 # 函数高级 if else if else 包管理 下载第三方包 比较热门的框架 for 循环 for 循环的几种写法 switch 语句 数组及数组切片 数组迭代 ...

  7. 【Trie】背单词

    参考博客: https://www.luogu.org/problemnew/solution/P3294 https://blog.csdn.net/VictoryCzt/article/detai ...

  8. Python如何将字符和Unicode编码转变

    小小总结一下,以防过几天忘记,自己的复习资料,如果能帮到大家,也是有所作用!! 1,字符转化为Unicode编码方法: ord("字符") ord("A") o ...

  9. Cache的一些总结

    输出缓存 这是最简单的缓存类型,它保存发送到客户端的页面副本,当下一个客户端发送相同的页面请求时,此页面不会重新生成(在缓存有限期内),而是从缓存中获取该页面:当然由于缓存过期或被回收,这时页面会重新 ...

  10. Eclipse MyEclipse 反编译.class文件 myeclipse source not found

    首先,需要下载两个必须的插件包. 一个是:准备反编译需要的jad.exe 下载地址:http://varaneckas.com/jad/ 二个是:反编译编辑器net.sf.jadclipse_3.3. ...