题面传送门

题意:

  • 求满足 \(1 \leq x \leq n\),\(1 \leq y \leq m\),\(\gcd(x,y)\) 为质数的数对 \((x,y)\) 的个数。
  • \(T\) 组询问。
  • \(1 \leq T \leq 10^4\),\(1 \leq n,m \leq 10^7\)。

今天终于学会了莫比乌斯反演反演~~,就写篇博客加深下印象吧。

要说这莫比乌斯反演有多么博大精深,就不得不从莫比乌斯函数 \(\mu(x)\) 说起。

我们定义 \(\mu(x)\) 为:

\[\mu(x)=\begin{cases}1&x=1\\(-1)^k&x=\prod\limits_{i=1}^kp_i\ \text{,}\ p_i\text{均为质数且互不相同}\\0&\text{otherwise}\end{cases}
\]

当然,\(\mu(x)\) 有不少有趣的性质,其中最重要且最常用的一条是:

\[\sum\limits_{d|n}\mu(d)=[n=1]
\]

为什么?其实很好理解。

当 \(x=1\) 时显然得证。

当 \(x \neq 1\) 时,设 \(n=\prod\limits_{i=1}^kp_i^{c_i},n'=\prod\limits_{i=1}^kp_i\)。

那么显然有 \(\sum\limits_{d|n}\mu(d)=\sum\limits_{d|n'}\mu(d)\)。

而 \(\sum\limits_{d|n'}\mu(d)=\sum\limits_{i=0}^k\dbinom{k}{i}\times (-1)^i\)。

由二项式定理易得原式 \(=0\)。故原命题成立。

那这形式诡异的莫比乌斯函数对我们解题能有什么帮助呢?

这就要引入一个更加神的知识:莫比乌斯反演。

何谓反演?相信不少刚学莫比乌斯反演的人都会有这样的疑问。

回忆起圆的反演。如果存在圆 \(O\) 与点 \(P\) 与 \(P'\) 使得 \(O,P,P'\) 共线且 \(|OP| \times |OP'|=r^2\),那么就称“\(P\) 与 \(P'\) 互为圆 \(O\) 的反演点”。知道了 \(P\) 的位置,\(P'\) 的位置也确定下来了。反之亦然。

莫比乌斯反演也类似。假设我们有两个函数 \(f(n),F(n)\),满足 \(F(n)=\sum\limits_{d|n}f(d)\),那么 \(f(n)=\sum\limits_{d|n}\mu(d)F(\dfrac{n}{d})\)。

怎么证明这个定理呢?最简单的方法是利用狄利克雷卷积来证明。可惜我不会, 5 天后咱再回头来看用狄利克雷卷积的解法。这里介绍一种纯推式子的方法:

\[\begin{aligned}\sum\limits_{d|n}\mu(d)F(\dfrac{n}{d})&=\sum\limits_{d|n}\mu(d)\sum\limits_{p|\frac{n}{d}}f(p)\\&=\sum\limits_{dp|n}f(p)\mu(d)\\&=\sum\limits_{p|n}f(p) \times \sum\limits_{d|\frac{n}{p}}\mu(d)\\&=\sum\limits_{p|n}f(p) \times [\frac{n}{p}=1]\\&=f(n)\end{aligned}
\]

同时,还有第二种形式的莫比乌斯反演。如果 \(F(n)=\sum\limits_{n|d}f(n)\),那么 \(f(n)=\sum\limits_{n|d}\mu(\frac{d}{n})F(d)\)。证明方法与第一种形式的莫比乌斯反演几乎一样,这里就不再赘述了。


说了这么多,相信大家对莫比乌斯反演有了一定的了解。那么莫比乌斯函数及莫比乌斯反演怎样真正应用在题目中呢?我们就以这道题为例来看一看。

很自然地想到枚举 \(\gcd\),即 \(\sum\limits_{p \in prime}\sum\limits_{i=1}^n\sum\limits_{j=1}^m[\gcd(i,j)=p]\)。

下面就是套路了。令 \(f(d)=\sum\limits_{i=1}^n\sum\limits_{j=1}^m[\gcd(i,j)=d]\),\(F(d)=\sum\limits_{i=1}^n\sum\limits_{j=1}^m[d|\gcd(i,j)]\)。

显然 \(F(p)=\sum\limits_{p|d}f(d)\)。

套用第二种形式的莫比乌斯反演得 \(f(p)=\sum\limits_{p|d}\mu(\frac{d}{p})F(d)\)。

这样转化有什么好处呢?不难发现要求 \(f(d)\) 非常棘手,但是要求 \(F(d)\) 非常容易————\(F(d)=\lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor\)

一不做二不休,把 \(F(d)\) 带回原式得 \(f(p)=\sum\limits_{p|d}\mu(\frac{d}{p})\lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor\)

最后计算答案。\(ans=\sum\limits_{p \in prime}f(p)=\sum\limits_{p \in prime}\sum\limits_{p|d}\mu(\frac{d}{p})\lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor=\sum\limits_{d=1}^n\lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor\sum\limits_{p|d \operatorname{and} p \in prime}\mu(\frac{d}{p})\)

记 \(t_d=\sum\limits_{p|d \operatorname{and} p \in prime}\mu(\frac{d}{p})\),显然可以在 \(\mathcal O(n \log n)\) 的时间复杂度内求出所有 \(t_d\)。还是把 \(t_d\) 带回去,\(ans=\sum\limits_{d=1}^n\lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor t_d\)。

如果单次询问那么的确一遍循环就可以了。可是本题有 \(10^4\) 组数据,出题人显然不会放过 \(\mathcal O(nT)\) 解法。如何进行优化呢?


考虑一个特别经典的问题,求 \(\sum\limits_{i=1}^n\lfloor \frac{n}{i} \rfloor\)。

显然,暴力的 \(\mathcal O(n)\) 的解法是不能被接受的。

不过仔细观察就会发现一个性质:有不少重复的 \(\lfloor \frac{n}{i} \rfloor\),而且 \(\lfloor \frac{n}{i} \rfloor\) 相同的 \(i\) 是成段分部的。

故我们可以找出 \(\lfloor \frac{n}{i} \rfloor\) 相同的段然后计算贡献。最多有 \(2 \sqrt{n}\) 个这样的段。

这就是著名的整除分块的思想。

回到本题来。使用类似的套路,找出 \(\lfloor \frac{n}{i} \rfloor\) 与 \(\lfloor \frac{m}{i} \rfloor\) 都相同的 \(i\)——它们也一定是成段分部的,使用前缀和计算贡献就完事了。

时间复杂度 \(\mathcal O(T\sqrt{n}+n \log n)\)。

  1. /*
  2. Contest: -
  3. Problem: P2257
  4. Author: tzc_wk
  5. Time: 2020.8.31
  6. */
  7. #include <bits/stdc++.h>
  8. using namespace std;
  9. #define fi first
  10. #define se second
  11. #define pb push_back
  12. #define fz(i,a,b) for(int i=a;i<=b;i++)
  13. #define fd(i,a,b) for(int i=a;i>=b;i--)
  14. #define foreach(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
  15. #define all(a) a.begin(),a.end()
  16. #define fill0(a) memset(a,0,sizeof(a))
  17. #define fill1(a) memset(a,-1,sizeof(a))
  18. #define fillbig(a) memset(a,0x3f,sizeof(a))
  19. #define y1 y1010101010101
  20. #define y0 y0101010101010
  21. typedef pair<int,int> pii;
  22. typedef long long ll;
  23. inline int read(){
  24. int x=0,neg=1;char c=getchar();
  25. while(!isdigit(c)){
  26. if(c=='-') neg=-1;
  27. c=getchar();
  28. }
  29. while(isdigit(c)) x=x*10+c-'0',c=getchar();
  30. return x*neg;
  31. }
  32. int T=read();
  33. bool vis[10000005];
  34. ll mu[10000005],pri[5000005],sum[10000005],t[10000005],pcnt=0;
  35. inline void get_mu(){
  36. mu[1]=1;
  37. for(int i=2;i<=10000000;i++){
  38. if(!vis[i]){mu[i]=-1;pri[++pcnt]=i;}
  39. for(int j=1;j<=pcnt&&pri[j]*i<=10000000;j++){
  40. vis[i*pri[j]]=1;
  41. if(i%pri[j]==0) break;
  42. else mu[pri[j]*i]=-mu[i];
  43. }
  44. }
  45. for(int i=1;i<=pcnt;i++) for(int j=1;j*pri[i]<=10000000;j++) t[j*pri[i]]+=mu[j];
  46. for(int i=1;i<=10000000;i++) sum[i]=sum[i-1]+t[i];
  47. }
  48. int main(){
  49. get_mu();
  50. while(T--){
  51. int n=read(),m=read();
  52. ll ans=0;
  53. for(int l=1,r;l<=min(n,m);l=r+1){
  54. r=min(n/(n/l),m/(m/l));
  55. ans+=1ll*(n/l)*(m/l)*(sum[r]-sum[l-1]);
  56. }
  57. printf("%lld\n",ans);
  58. }
  59. return 0;
  60. }

洛谷 P2257 - YY的GCD(莫比乌斯反演+整除分块)的更多相关文章

  1. 洛谷 - P2257 - YY的GCD - 莫比乌斯反演 - 整除分块

    https://www.luogu.org/problemnew/show/P2257 求 \(n,m\) 中 \(gcd(i,j)==p\) 的数对的个数 求 $\sum\limits_p \sum ...

  2. 洛谷P2257 YY的GCD 莫比乌斯反演

    原题链接 差不多算自己推出来的第一道题QwQ 题目大意 \(T\)组询问,每次问你\(1\leqslant x\leqslant N\),\(1\leqslant y\leqslant M\)中有多少 ...

  3. 洛谷 P2257 YY的GCD

    洛谷 P2257 YY的GCD \(solution:\) 这道题完全跟[POI2007]ZAP-Queries (莫比乌斯反演+整除分块) 用的一个套路. 我们可以列出答案就是要我们求: \(ans ...

  4. [BZOJ 2820] YY的gcd(莫比乌斯反演+数论分块)

    [BZOJ 2820] YY的gcd(莫比乌斯反演+数论分块) 题面 给定N, M,求\(1\leq x\leq N, 1\leq y\leq M\)且gcd(x, y)为质数的(x, y)有多少对. ...

  5. 洛谷P2257 YY的GCD(莫比乌斯反演)

    传送门 原来……莫比乌斯反演是这么用的啊……(虽然仍然不是很明白) 首先,题目所求如下$$\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=prim]$$ 我们设$f(d)$表示$g ...

  6. 洛谷 P2257 YY的GCD 题解

    原题链接 庆祝: 数论紫题 \(T4\) 达成! 莫比乌斯 \(T1\) 达成! yy 真是个 神犇 前记 之前我觉得: 推式子,直接欧拉筛,筛出个 \(\phi\),然后乱推 \(\gcd\) 就行 ...

  7. 洛谷P2257 YY的GCD

    今日份是数论 大概是..从小学奥数到渐渐毒瘤 那就简单列一下目录[大雾 同余 质数密度 唯一分解定理 互质 完全剩余系 简化剩余系 欧拉函数 逆元 斐蜀定理 阶(及其性质) 欧拉定理 费马小定理 原根 ...

  8. Luogu P2257 YY的GCD 莫比乌斯反演

    第一道莫比乌斯反演...$qwq$ 设$f(d)=\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)==d]$ $F(n)=\sum_{n|d}f(d)=\lfloor \frac{N ...

  9. Bzoj 2820: YY的GCD(莫比乌斯反演+除法分块)

    2820: YY的GCD Time Limit: 10 Sec Memory Limit: 512 MB Description 神犇YY虐完数论后给傻×kAc出了一题给定N, M,求1<=x& ...

随机推荐

  1. Golang通脉之数据类型

    标识符与关键字 在了解数据类型之前,先了解一下go的标识符和关键字 标识符 在编程语言中标识符就是定义的具有某种意义的词,比如变量名.常量名.函数名等等. Go语言中标识符允许由字母数字和_(下划线) ...

  2. 【Takin使用日记】记一次TransmittableThreadLocal引起的业务异常

    对于常见的 WEB 容器,Takin 通过增强 org.apache.catalina.core.StandardHostValve#invoke 方法,拦截并解析方法入参的 Request 对象中的 ...

  3. 封装一个的toast弹出框(vue项目)

    逆风的方向,更适合飞翔 实现效果 实现步骤 先写出一个toast组件 // Toast.vue <template> <div id="toast" :class ...

  4. VS2015+OpenCV+Qt

    VS2015+OpenCV+Qt 01.OpenCV 下载 进入官网链接: https://opencv.org,下载所需要的版本: 下载完成后直接双击,选择解压路径,解压到响应的文件夹中: 若之后需 ...

  5. C++学习笔记之pimpl用法详解

    原文链接:https://www.jb51.net/article/122557.htm 在编写稳定代码是,管理好代码间的依赖性是不可缺少的一个环节.特别是库文件的编写中,减少代码间的依赖性可以提供一 ...

  6. 五分钟搞懂spring-cloud-square

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 初识spring-cloud-square 2021年 ...

  7. NavigationView使用简介

    Android支持直接创建带有NavigationView的Activity,这里主要介绍NavigationView的逻辑. NavigationView通常是跟DrawerLayout一起使用.D ...

  8. Get_init_color_map

    #!/bin/bash./simulate_screencap.sh./analysis_screencap.py

  9. 为什么IDEA不推荐你使用@Autowired ?

    @Autowired注解相信每个Spring开发者都不陌生了!在DD的Spring Boot基础教程和Spring Cloud基础教程中也都经常会出现. 但是当我们使用IDEA写代码的时候,经常会发现 ...

  10. 计算机网络-3-2-点对点协议PPP

    点对点协议PPP 在通信链路较差的年代,在数据链路层使用可靠传输协议曾经是一种好方法,比较简单的点对点PPP协议则是目前使用最广泛的数据链路层协议. PPP协议的特点 互联网用户通过都要连接到某个IS ...