先看一道例题:
[POI2007]Zap

BZOJ

洛谷

题目大意:$T$ 组数据,求 $\sum^n_{i=1}\sum^m_{j=1}[gcd(i,j)=k]$

$1\leq T\leq 50000,1\leq k\leq n,m\leq 50000$

暴力做法 $O(Tnm\log\max(n,m))$ 不用说了,那有没有什么更好的做法呢?


我们定义一种函数叫莫比乌斯函数 $\mu$,它的定义是:

当 $n=1$ 时,$\mu(n)=1$

当 $n$ 可以分解成 $p_1p_2...p_k$,其中 $p_i$ 均为质数且互不相同时,$\mu(n)=(-1)^k$

否则 $\mu(n)=0$

莫比乌斯函数有一个性质是这样的:

$\sum_{d|n}\mu(d)=[n=1]$

这个性质暂时用不到,以后到狄利克雷卷积和杜教筛时才有用,所以只做了解。


开始正文:莫比乌斯反演。

情况一:

若函数 $F$ 和 $f$ 满足 $F(n)=\sum_{d|n}f(d)$

则 $f(n)=\sum_{d|n}\mu(d)F(\frac{n}{d})$

情况二:(用的较多,一定要死记硬背)

若函数 $F$ 和 $f$ 满足 $F(n)=\sum_{n|d}f(d)$

则 $f(n)=\sum_{n|d}\mu(\frac{d}{n})F(d)$

让我们来感性理解一下。设 $F$ 和 $f$ 满足:

$F(1)=f(1)$

$F(2)=f(1)+f(2)$

$F(3)=f(1)+f(3)$

$F(4)=f(1)+f(2)+f(4)$

$F(5)=f(1)+f(5)$

$F(6)=f(1)+f(2)+f(3)+f(6)$

$F(7)=f(1)+f(7)$

$F(8)=f(1)+f(2)+f(4)+f(8)$

$F(9)=f(1)+f(3)+f(9)$

$F(10)=f(1)+f(2)+f(5)+f(10)$

$...$

那么就有:

$f(1)=F(1)$

$f(2)=F(2)-F(1)$

$f(3)=F(3)-F(1)$

$f(4)=F(4)-F(2)$

$f(5)=F(5)-F(1)$

$f(6)=F(6)-F(3)-F(2)+F(1)$

$f(7)=F(7)-F(1)$

$f(8)=F(8)-F(4)$

$f(9)=F(9)-F(3)$

$f(10)=F(10)-F(5)-F(2)+F(1)$

我们单独把 $f(6)$ 提出来看(其他的类似)

$f(6)=F(6)-F(3)-F(2)+F(1)=\mu(1)F(6)+\mu(2)F(3)+\mu(3)F(2)+\mu(6)F(1)=\sum_{d|6}\mu(d)F(\frac{6}{d})$

实际上就是一个容斥原理。

证明较难,貌似要用狄利克雷卷积,此处略去。(其实是因为我太蒻了)

另外 $\mu$ 还是个积性函数,虽然现在也没什么用。

如何线性筛 $\mu$?

我们发现 $\mu(1)=1,\mu(prime)=-1$。

线筛的原理是搜到重复的质因子时退出,正好符合 $\mu$ 的第三条!

所以:

当 $prime[j]|i$ 时,$\mu(i\times prime[j])=0$

否则,$\mu(i\times prime[j])=-\mu(i)$

程序如下:

 void init(int n){
memset(vis,,sizeof(vis));
memset(mu,,sizeof(mu));
memset(prime,,sizeof(prime));
len=;
vis[]=true;
mu[]=; //预处理1
for(int i=;i<=n;i++){
if(!vis[i]){
mu[i]=-; //是质数,莫比乌斯函数=-1
prime[++len]=i;
}
for(int j=;j<=len && i*prime[j]<=n;j++){
int k=i*prime[j];
vis[k]=true;
if(i%prime[j]==) break; //有重复质因子,莫比乌斯函数=0
else mu[k]=-mu[i]; //多了一个不重复质因子,莫比乌斯函数区相反数
}
}
}

莫比乌斯反演大部分题目都含有 $gcd$,套路就看例题,大部分题目都一样的。


回到原题。

$T$ 组数据,求 $\sum^n_{i=1}\sum^m_{j=1}[gcd(i,j)=k]$

开始讲这类题目的套路:

假设 $n<m$。

设两个函数:

$f(x)=\sum^n_{i=1}\sum^m_{j=1}[gcd(i,j)=x]$

$F(x)=\sum^n_{i=1}\sum^m_{j=1}[x|gcd(i,j)]$

题目要求即为 $f(k)$。

我们发现在 $F(x)$ 中有序对 $(i,j)$ 对答案作出 $1$ 的贡献当且仅当 $x|i$ 且 $x|j$。

这样的 $i$ 有 $\lfloor\frac{n}{x}\rfloor$ 个,$j$ 有 $\lfloor\frac{m}{x}\rfloor$ 个。

所以 $F(x)=\lfloor\frac{n}{x}\rfloor\lfloor\frac{m}{x}\rfloor$

根据定义,$F(x)=\sum^n_{x|d}f(d)$

莫比乌斯反演一波:$f(x)=\sum^n_{x|d}\mu(\frac{d}{x})F(d)$

题目要求就变成了:$f(k)=\sum^n_{k|d}\mu(\frac{d}{k})F(d)$

我们发现当且仅当 $d$ 是 $k$ 的倍数时对答案有贡献,那我们可以改一下枚举的方式:

$f(k)=\sum^{\lfloor\frac{n}{k}\rfloor}_{d=1}\mu(d)F(dk)$

把 $F(dk)$ 替换:$f(k)=\sum^{\lfloor\frac{n}{k}\rfloor}_{d=1}\mu(d)\lfloor\frac{n}{dk}\rfloor\lfloor\frac{m}{dk}\rfloor$

$d$ 看着不爽:$f(k)=\sum^{\lfloor\frac{n}{k}\rfloor}_{i=1}\mu(i)\lfloor\frac{n}{ik}\rfloor\lfloor\frac{m}{ik}\rfloor$

此时这个式子已经可以做到 $O(n)$ 计算了,线性筛出 $\mu$ 然后扫一遍就行了。

等等,$T$ 组数据,$O(Tn)$?


阅读以下内容以前请先学会前置技能整除分块

我们发现这里有个很明显的整除分块的形式,那么我们可以考虑 $[l,r]$ 这段区间,其中 $\lfloor\frac{n}{ik}\rfloor=\lfloor\frac{n}{jk}\rfloor=x$ 且 $\lfloor\frac{m}{ik}\rfloor=\lfloor\frac{m}{jk}\rfloor=y:i,j\in[l,r]$

$\ \sum^r_{i=l}\mu(i)\lfloor\frac{n}{ik}\rfloor\lfloor\frac{m}{ik}\rfloor$

$=\sum^r_{i=l}\mu(i)xy$

$=xy\sum^r_{i=l}\mu(i)$

那么我们只需要求出 $\mu$ 的前缀和,然后整除分块套上去即可。

还可以加一个常数优化:

我们发现,在原式中,只要出现了 $n$ 和 $m$ 的地方都是 $\lfloor\frac{n}{ik}\rfloor$ 和 $\lfloor\frac{m}{ik}\rfloor$ 的形式。

考虑到 $\lfloor\frac{n}{ik}\rfloor=\lfloor\frac{\frac{n}{k}}{i}\rfloor$,我们可以在开始整除分块之前就 $n$ 和 $m$ 除以 $k$ 然后再分块,可以少掉一个 $\sqrt{k}$ 的常数。


代码如下:时间复杂度 $O(T\sqrt{n})$,空间复杂度 $O(n)$

#include<bits/stdc++.h>
using namespace std;
int t,n,m,k;
int prime[],mu[],pre[],len;
bool vis[];
void init(int x){
vis[]=true;
mu[]=;
for(int i=;i<=x;i++){
if(!vis[i]){
mu[i]=-;
prime[++len]=i;
}
for(int j=;j<=len && i*prime[j]<=x;j++){
int k=i*prime[j];
vis[k]=true;
if(i%prime[j]==) break;
else mu[k]=-mu[i];
}
}
for(int i=;i<=x;i++) pre[i]=pre[i-]+mu[i];
}
int main(){
init();
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&m,&k);
n/=k;m/=k;
int ans=;
for(int l=,r;l<=min(n,m);l=r+){
r=min(n/(n/l),m/(m/l));
ans+=(n/l)*(m/l)*(pre[r]-pre[l-]);
}
printf("%d\n",ans);
}
}

莫比乌斯反演

然后推荐几题:

洛谷P2522  BZOJ2301 [HAOI2011]Problem b (题解待填充)

洛谷P2257 YY的GCD (题解待填充)

洛谷P1447 BZOJ2005 [NOI2010]能量采集 (题解待填充)

莫比乌斯反演学习笔记+[POI2007]Zap(洛谷P3455,BZOJ1101)的更多相关文章

  1. 扩展中国剩余定理学习笔记+模板(洛谷P4777)

    题目链接: 洛谷 题目大意:求同余方程组 $x\equiv b_i(mod\ a_i)$ 的最小正整数解. $1\leq n\leq 10^5,1\leq a_i\leq 10^{12},0\leq ...

  2. 莫比乌斯反演学习笔记(转载自An_Account大佬)

    转载自An_Account大佬 提示:别用莫比乌斯反演公式,会炸的 只需要记住: [gcd(i,j)=1]=∑d∣gcd(i,j)μ(d)[gcd(i,j)=1]=\sum_{d|gcd(i,j)}\ ...

  3. 【笔记篇】不普及向——莫比乌斯反演学习笔记 && 栗题HAOI2011 Problem B

    Part0 广告(当然没有广告费) P.S. 这篇文章是边学着边用Typora写的...学完了题A了blog也就呼之欲出了~有latex化式子也非常方便...非常建议喜欢Markdown的dalao们 ...

  4. 洛谷 P3455&BZOJ1101 【[POI2007]ZAP-Queries】

    这应该是入坑莫比乌斯反演的第一道题了吧 其实题目让我们求的东西很简单,就是 \[ ans=\sum_{i=1}^{a}\sum_{j=1}^{b}\left [ gcd(i,j)=k \right ] ...

  5. LCT模板(学习笔记)(洛谷3690)(加边,删边,修改点权)

    最近学习了一波LCT qwq 强势安利Flashhu的博客!!!!! 真的特别详细(可惜我不会弄链接) 如果有想要学习\(LCT\)的同学,可以直接看他的博客 我这里就简单写一点自己的体会啊. \(L ...

  6. 洛谷P3455 ZAP-Queries [POI2007] 莫比乌斯反演+数论分块

    正解:莫比乌斯反演 解题报告: 传送门! 首先这题刚看到就很,莫比乌斯反演嘛,和我前面写了题解的那个一模一样的,所以这儿就不讲这前边的做法辣QAQ 但是这样儿还有个问题,就现在已知我每次都是要O(n) ...

  7. 洛谷P3455 [POI2007]ZAP-Queries (莫比乌斯反演)

    题意:求$\sum_{i=1}^{a}\sum_{j=1}^{b}[gcd(i,j)==d]$(1<=a,b,d<=50000). 很套路的莫比乌斯反演. $\sum_{i=1}^{n}\ ...

  8. 洛谷P3455 [POI2007]ZAP-Queries

    题目大意: 给定\(n,m,k,\) 求 \[\sum\limits_{x=1}^n\sum\limits_{y=1}^m[gcd(x,y)==k]\] 莫比乌斯反演入门题,先进行一步转化,将每个\( ...

  9. 洛谷P3455 [POI2007]ZAP-Queries(莫比乌斯反演)

    传送门 设$$f(k)=\sum_{i=1}^{a}\sum_{j=1}^{b}[gcd(i,j)=k]$$ $$g(n)=\sum_{n|k}f(k)=\lfloor\frac{a}{n}\rflo ...

随机推荐

  1. 2.2《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)——列表

    也许最常用的Unix命令是ls了,它是'list'的简写(Listing 8) Listing 8 用ls以列表的形式显示文件和目录(内容输出跟各自电脑有关) $ ls Desktop Downloa ...

  2. 【第九课】MriaDB密码重置和慢查询日志

    目录 1.如何进行修改MariaDB的密码 2.Mariadb的慢查询日志 1.如何进行修改MariaDB的密码 记得root密码的修改方式: [root@localhost ~]# mysqladm ...

  3. [hdu5503]EarthCup[霍尔定理]

    题意 一共 \(n\) 只球队,两两之间会进行一场比赛,赢得一分输不得分,给出每只球队最后的得分,问能否构造每场比赛的输赢情况使得得分成立.多组数据 \(T\le 10,n\le 5\times 10 ...

  4. [BZOJ3693]圆桌会议[霍尔定理+线段树]

    题意 题目链接 分析 又是一个二分图匹配的问题,考虑霍尔定理. 根据套路我们知道只需要检查 "区间的并是一段连续的区间" 这些子集. 首先将环倍长.考虑枚举答案的区间并的右端点 \ ...

  5. SpringBoot整合EHcache学习笔记

    为了提高系统的运行效率,引入缓存机制,减少数据库访问和磁盘IO.下面说明一下ehcache和SpringBoot整合配置 前言介绍 EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特 ...

  6. 【Android UI设计与开发】第04期:引导界面(四)仿人人网V5.9.2最新版引导界面

    这一篇我将会以人人网的引导界面为实例来展开详细的讲解,人人网的引导界面比较的新颖,不同于其他应用程序千篇一律的靠滑动来引导用户,而是以一个一个比较生动形象的动画效果展示在用户们的面前,有一种给人眼前一 ...

  7. vue-router单页应用简单示例(三)

    用vue-resource向服务器请求数据 我们主要来了解一下以下内容: 模拟服务端返回数据 用vue-resource向服务器请求数据 模拟服务器返回数据   我们用vue-cli创建的项目中,已经 ...

  8. Linux+Nginx+Asp.net Core及守护进程部署

    上篇<Docker基础入门及示例>文章介绍了Docker部署,以及相关.net core 的打包示例.这篇文章我将以oss.offical.site站点为例,主要介绍下在linux机器下完 ...

  9. hyperledger-fabirc1.2-ca-server的生产示例

    hyperledger-fabirc1.2-ca-server的生产示例,带TLS 在fabirc-samples/first-network中启动网络,其ca证书是利用crypto的工具生成的,但是 ...

  10. 无前趋的顶点优先的拓扑排序方法(JAVA)(转载http://128kj.iteye.com/blog/1706968)

    无前趋的顶点优先的拓扑排序方法 该方法的每一步总是输出当前无前趋(即人度为零)的顶点,其抽象算法可描述为:     NonPreFirstTopSort(G){//优先输出无前趋的顶点       w ...