既然选择了远方,便只顾风雨兼|

H_W_Y

园龄:1年11个月粉丝:28关注:15

Number Theory(4)

11 莫比乌斯函数

尝试按照《具体数学》的顺序引入莫比乌斯反演。


11.1 引入

莫比乌斯函数 μ(m) 是根据 19 世纪的数学家奥古斯特·莫比乌斯命名的,他还发现了著名的莫比乌斯带,μ(m) 对所有整数 m1 由等式

dmμ(d)=[m=1]

来定义。

这个式子实际上是一个递归式,左边的 μ(m) 和某些满足 d<mμ(d) 的值组成的和式。我们有相继带入前面 m,从而得到前面的值:1,1,1,0,1,1,1,0,0,1,1,0,

在 1857 年,Richard Dedekind 和 Joseph Liouville 注意到了如下重要的 “反演原理”。

g(m)=dmf(d)f(m)=dmμ(d)g(md)

这就是我们熟知的 莫比乌斯反演


发现这个东西的证明是容易的:如果 g(m)=dmf(d),那么

dmμ(d)g(md)=dmμ(md)g(d)=dmμ(md)kdf(k)=kmdmkμ(mkd)f(k)=kmdmkμ(d)f(k)=km[mk=1]f(k)=f(m)

反之,如果 f(m)=dmμ(d)g(md),则

dmf(d)=dmkdμ(k)g(dk)=dmkdμ(dk)g(k)=kmdmkμ(d)g(k)=km[mk=1]g(k)=g(m)

于是我们在这里就证明了 莫比乌斯反演

而莫比乌斯反演还可以被表示成

g=f1f=gμ


现在回到最开始的那个式子,发现其实就是 μ1=ϵ,由于我们之前证明的 积性函数的逆元也是积性函数,可以知道 μ 必是积性函数。这样一来,只要我们计算出 μ(pk) 就能算出 μ(m)

m=pk 时,根据最初的式子,我们知道对于所有 k1,都有

μ(1)+μ(p)+μ(p2)++μ(pk)=0

由此推出

μ(p)=1;μ(pk)=0,k>1

于是,我们就推出了 μ 的定义式

μ(m)={1m=10m(1)kkmω(m)


如果我们把之前的欧拉反演视作 φ(m) 的递归式,就能应用莫比乌斯反演得到

φ(m)=dmμ(d)md

也就是 μid=φ,也对狄利克雷卷积逆元有了另一个方面的解释。


接下来我们尝试用容斥的角度来理解莫比乌斯函数。

g(n)=ndf(d),即 g(n)f 在所有 n 的倍数处的取值和。现在已知 g,要求 f(1)。则 f(1) 等于 f1 的倍数处的取值和,减去在质数处的取值和,但是多减去了在两个不同质数乘积处的取值和,一次要加上这些值,但是多加了在三个不同质数乘积处的取值和,以此类推。因此,若 nk 个不同质数的乘积,则 f(1) 会收到 g(n) 系数为 (1)k 的贡献,如下图。

image

就是对 N 作容斥,得到贡献系数 μ


11.2 线性筛莫比乌斯函数

根据定义是,线性筛莫比乌斯函数是非常容易的。

  mu[1]=1;
  for(int i=2;i<=maxn;i++){
  	if(!vis[i]) p[++cnt]=i,mu[i]=-1;
  	for(int j=1;j<=cnt&&i*p[j]<=maxn;j++){
  	  vis[i*p[j]]=true;
	  if(i%p[j]==0) break;
	  mu[i*p[j]]=-mu[i];	
	}
  }

11.3 常见技巧

对于 莫比乌斯反演,我们常常用式子

[gcd(i,j)=1]=dgcd(i,j)μ(d)

它把 gcd(i,j) 带入了 n,还将 i,j 互质的条件转化为枚举 gcd(i,j) 的约数 d,然后对 μ(d) 求和。在 i,j 同样需要枚举的时候,可以先枚举 d 并计算合法的 (i,j) 对数,这样 i,j 合法当且仅当 di,dj,就把 i,j 独立开了。

于是我们就可以这样解决下面的式子:

i=1nj=1m[gcd(i,j)=1]=i=1nj=1mdgcd(i,j)μ(d)=d=1min(n,m)μ(d)i=1nj=1m[didj]=d=1min(n,m)μ(d)ndmd

相当于对最大公约数为 d 的倍数进行了容斥:加上最大公约数为 1 的倍数的对数,减去最大公约数为 pi 的倍数的对数,加上最大公约数为 pipj(ij) 的倍数的对数,以此类推。得到每个 d 的贡献系数就是莫比乌斯函数。

而这个式子是非常容易用整除分块完成。


d(ij)=xiyj[xy] 考虑单个质因子 p,再用中国剩余定理和并。设 a=vp(i)i 中含有质因子 p 的数量,b=vp(j),则 vp(ij)=a+b。对于 ij 的约数 d,若 vp(d)a,则令其对应 vp(x)=vp(d),vp(y)=0,即所有都算在 x 上面;若 vp(d)>a,则令其对应 vp(x)=0,vp(y)=vp(d)a。容易发现这样会形成双射,因此可证得这一结论。

11.4 例题

接下来,我们来将一些例题,由于比较多,所以单独提出来了。部分例题会用到上面的常见技巧。

前面的一些例题中有些写得比较简略,有些可能是👻乐团中的子问题,如果看不懂可以在那道题题解中找一下,或者直接问我。


P2522 [HAOI2011] Problem b

对于给出的 n 个询问,每次求有多少个数对 (x,y),满足 axbcyd,且 gcd(x,y)=kgcd(x,y) 函数为 xy 的最大公约数。

1n,k5×1041ab5×1041cd5×104

首先可以对式子做一个二维差分,转换成求下界为 1 的式子

i=1nj=1m[gcd(i,j)=k]

我们把 i,j÷k 就可以得到

i=1nkj=1mk[gcd(i,j)=1]

这就是一个经典的莫反式子,直接作就可以得到

d=1min(nk,mk)μ(d)nkdmkd

于是就可以用整除分块在 O(n+Tn) 时间内完成。代码


子问题:P3455 [POI2007] ZAP-Queries


P2257 YY的GCD

给定 N,M,求 1xN1yMgcd(x,y) 为质数的 (x,y) 有多少对。

T=104N,M107

问题就是求

i=1nj=1m[gcd(i,j)=P]

我们用莫反相关知识对其进行推导可以得到

=pPi=1nj=1m[gcd(i,j)=p]=pPi=1npj=1mp[gcd(i,j)=1]=pPd=1min(np,mp)μ(d)npdmpd

于是我们令 T=pd,那么可以得到

T=1min(n,m)nTmTpTpPμ(Tp)

前面可以直接用整除分块完成,而后面的 pTpPμ(Tp) 乍一眼是不好完成的。

但细想发现这是可以和莫比乌斯函数一起在线性筛中解决的,所以我们就可以直接预处理出其前缀和,从而做到时间复杂度 O(n+Tn)代码


双倍经验:P2568 GCD


SP5971 LCMSUM - LCM Sum

T 次询问,每次询问给出 n,求

i=1nlcm(i,n)

1T3×105,1n106

首先我们考虑把 lcm 转化成 gcd,那么

i=1nlcm(i,n)=i=1ningcd(i,n)=ni=1nigcd(i,n)=ndn1di=1ni[gcd(i,n)=d]=ndn1di=1ndid[gcd(i,nd)=1]=ndni=1ndi[gcd(i,nd)=1]

我们设

F(n)=i=1ni[gcd(i,n)=1]

只要我们求出这个,就可以计算上面的式子了。


首先我们可以暴力用莫反计算,也就是

F(n)=i=1nididnμ(d)=dnμ(d)dnd(nd+1)2=n2dnμ(d)(nd+1)

我们发现后面可以被拆成 μ(id+1)=μid+μ1=φ+ϵ,于是我们就可以得到

n(φ(n)+ϵ(n))2


还有另外一种方法就是对与 n 互质的数进行分析,如果 xn 则一定有 (nx)n,那么我们把它两两配对,就有 nφ(n)2

而显然 F(1)=1


现在原式就变成了

ndnd(φ(d)+ϵ(d))2=n2(1+dndφ(d))

而这里的 dndφ(d)=1(id×φ) 是可以用线性筛筛出来的,于是总时间复杂度 O(T+n)代码


P4318 完全平方数

n 次询问,每次询问给出一个 k,查询第 k 个不是完全平方数的正整数倍数的数。

1k109,1n50

f(n) 表示 n 的非完全平方数倍数的数,那么我们最后只需要二分答案即可。

怎么求 f(n) 呢?

发现可以先去掉 4,9, 的倍数,而接下来就要加上 (p1p2)2 的倍数,这不难让我们想到莫比乌斯函数。

相当于做容斥,那么我们就有

f(n)=i=1μ(i)ni2

直接计算,时间复杂度 O(nlogn)代码


P1829 [国家集训队] Crash的数字表格 / JZPTAB

给定 n,m,求

i=1nj=1mlcm(i,j)

1n,m107

i=1nj=1mlcm(i,j)=i=1nj=1mijgcd(i,j)=d=1mindi=1ndj=1md[gcd(i,j)=1]ij

后面的式子就和 SP5971 一样了。直接做就是线性的。代码


P3704 [SDOI2017] 数字表格

Doris 刚刚学习了 fibonacci 数列。用 fi 表示数列的第 i 项,那么

f0=0,f1=1

fn=fn1+fn2,n2

Doris 用老师的超级计算机生成了一个 n×m 的表格,

i 行第 j 列的格子中的数是 fgcd(i,j),其中 gcd(i,j) 表示 i,j 的最大公约数。

Doris 的表格中共有 n×m 个数,她想知道这些数的乘积是多少。

答案对 109+7 取模。

1T1031n,m106

稍微推一下式子就是

i=1nj=1mfgcd(i,j)=d=1min(n,m)fdi=1nj=1m[gcd(i,j)=d]=d=1min(n,m)fdi=1ndj=1md[gcd(i,j)=1]=d=1min(n,m)fdi=1ndj=1mdti,tjμ(t)=d=1min(n,m)fdt=1min(nd,md)μ(t)ntdmtd=T=1min(n,m)(dTfdμ(Td))nTmT

预处理一下括号内的东西,整除分块之后可以做到单次 O(n)


P5221 Product

给定 n,求

i=1nj=1nlcm(i,j)gcd(i,j)(mod104857601)

1n106,时限 200ms

有些人喜欢在写完👻之后来写这道题。


话不多说,直接暴力推一下式子就是了。

i=1nj=1nlcm(i,j)gcd(i,j)=i=1nj=1nijgcd(i,j)2=(i=1ni)2n1(i=1nj=1mgcd(i,j))2

前面的直接阶乘处理一下,后面的我们枚举 gcd 就可以得到

i=1nj=1mgcd(i,j)=d=1ndi=1ndj=1nd[gcd(i,j)=1]=d=1ndt=1ndμ(t)ndt2

于是两次整除分块就可以线性完成了,代码相当好些。代码


P3911 最小公倍数之和

对于 a1,a2,,an,求

i=1nj=1nlcm(ai,aj)

1n,ai5×104

给定具体的数是不好处理的,所以我们考虑先令 ci=j=1n[aj=i],即 i 的出现次数,而 V 为值域。

那么

i=1nj=1nlcm(ai,aj)=i=1nj=1naiajgcd(ai,aj)=d=1Vi=1nj=1naiajd[gcd(ai,aj)=d]=d=1Vi=1Vj=1Vijcicjd[gcd(i,j)=d]=d=1Vdi=1Vdj=1Vdijcidcjd[gcd(i,j)=1]=d=1Vdi=1Vdj=1Vdijcidcjdkikjμ(k)=d=1Vdk=1Vdμ(k)k2i=1Vkdj=1Vkdijcikdcjkd

我们令 T=kd 就可以得到

=T=1VdTμ(d)d2Tdi=1VTj=1VTijciTcjT=T=1VT(dTμ(d)d)(i=1VTiciT)2

于是只要我们令 f(T)=dTμ(d)d,g(T)=i=1VTiciT,原式就变成

T=1VTf(T)g2(T)

其中 f 可以在线性筛中处理出来,而 g 可以采取暴力枚举倍数和狄利克雷后缀和做到 O(VlnV)O(VlnlnV)

这样就做完了,查询时可以直接线性完成。代码。(暴力枚举计算 g


双倍经验:AGC038C LCMs


CF1285F Classical?

n 个整数 a1,a2,,an,求 max1i<jn(lcm(ai,aj))

2n105,1 ai105

求完了和,我们现在来求 max


考虑加上一个 gcd(ai,aj)=1 的条件。于是我们从大到小枚举每一个数,如果当前加入一个数 x,存在一个 >x 的数 y 满足 gcd(x,y)=1,那么所有 xzy 中间的所有 z 都是没有用的,因为与他们互质的数比 x 小了。

容易发现这是可以用单调栈直接维护的,那么我们如何计算出是否有与 x 互质的数呢?

通过上面有关 μ 的容斥原理,我们设 cntd 表示 d 的倍数的出现次数,那么答案就是

dxμ(d)cntd

只要这个值不为 0,我们就可以一直弹栈找到与它互质的那个数。

时间复杂度 O(i=1nd(i)),也就是 O(VlogV)


而对于 gcd1lcm 如何计算?

我们可以枚举每一个 gcd 都这样做一次,这样的时间复杂度是 O(Vlog2V) 的,但是它并不优秀。

发现如果 gcd(x,y)1,那么对于 ax,by,一定存在一组 (a,b) 满足 gcd(a,b)=1,lcm(a,b)=lcm(x,y),于是我们把所有 ai 的因数都加到集合中,一起跑上面的算法,时间复杂度还是 O(VlogV)代码


P3327 [SDOI2015] 约数个数和

给定 n,m,求

i=1nj=1md(ij)

1T,n,m50000

在常见技巧中,我们列出了整个式子的转化。

于是式子就是

i=1nj=1md(ij)=i=1nj=1mxiyj[xy]=i=1nj=1mxiyj[gcd(x,y)=1]

于是直接对这个式子莫反就可以得到

d=1min(n,m)μ(d)x=1ndy=1mdnxdmyd

g(n)=i=1nni,这时可以用整除分块预处理出来的。

于是式子就是

d=1min(n,m)μ(d)g(nd)g(md)

直接整除分块可以做到时间复杂度 O(nn+Tn)代码


P4619 [SDOI2018] 旧试题

给定 A,B,C

(i=1Aj=1Bk=1Cd(ijk))mod(109+7)

1A,B,C105,1T10

更为厉害的约数个数和。


多了一个变量,但是按照之前的转化方式是类似的

d(ijk)=uivjwk[gcd(u,v)=1][gcd(v,w)=1][gcd(u,w)=1]

那么我们就可以对这个东西进行莫反了

i=1Aj=1Bk=1Cd(ijk)=i=1Aj=1Bk=1Cuivjwk[gcd(u,v)=1][gcd(v,w)=1][gcd(u,w)=1]=u=1Ai=1Auv=1Bj=1Bvw=1Ck=1Cw[gcd(u,v)=1][gcd(v,w)=1][gcd(u,w)=1]=i=1Aj=1Bk=1CAiBjCkuiujμ(u)vivkμ(v)wjwkμ(w)=u=1min(A,B)v=1min(A,C)w=1min(B,C)μ(u)μ(v)μ(w)lcm(u,v)iAilcm(u,w)jBjlcm(v,w)kCk

我们可以令 fa(i)=ijAj,fb(i)=ijBj,fc(i)=ijCj,那么这是可以直接枚举倍数在 O(nlnn) 的时间复杂度内预处理出来的,计算时就变成了

u=1min(A,B)v=1min(A,C)w=1min(B,C)μ(u)μ(v)μ(w)fa(lcm(u,v))fb(lcm(u,w))fc(lcm(v,w))

然后你发现这还是 O(n3) 的,莫反根本没有用!


真的没有用吗?这个式子在哪些地方是有值的呢?

容易发现我们首先需要保证 μ(u),μ(v),μ(w) 都不是 0,并且 lcm(u,v)A,lcm(u,w)B,lcm(v,w)C

那么也就是对于任意的两个点,它们可以成为一组就意味着 μ(u)0,μ(v)0,lcm(u,v)max(A,B,C),然后我们尝试把这样的二元组建立一条边,边权为 lcm(u,v)


这个做法看起来根本不可行,并且直接这样建边是 O(n2) 的。

但是细想一下,这个条件是相当严的,要求 u,v,gcd(u,v) 都不能出现平方因子。于是我们可以先枚举 gcd(u,v),再分别枚举 ugcd(u,v)vgcd(u,v) 在枚举的过程中判断 μ(gcd),μ(u),μ(v)0ugcd(u,v)vgcd(u,v)

每一次我们枚举了质数的子集,而 105 内只会出现 6 个不同的质数,所以这样枚举下来是 O(m) 的!

下面给出这一部分的代码实现。

  for(int g=1;g<=mx;g++)
    for(int i=1;i*g<=mx;i++)
	  if(mu[i*g])
	    for(int j=i+1;1ll*i*j*g<=mx;j++)
		  if(mu[j*g]&&gcd(i,j)==1){
            int u=i*g,v=j*g,w=i*j*g;
			/*...*/
		  }

进而,我们发现这样的点对并不多,实测发现只有 760741 个!赢麻了!


那么现在成了怎么找三元环,可以尝试阅读 这篇博客

也就是我们将无向边定向,每一条边从度数大的点连向度数小的,然后这样去枚举的时间复杂度就是 O(mm),具体可以看上面的链接。

于是我们就做完了!直接枚举就可以了。

  for(int x=1;x<=mx;x++){
    for(auto i:G[x]) vis[i.fi]=i.se;
    for(auto i:G[x]){
	  int y=i.fi,wxy=i.se;
      for(auto j:G[y]){
		if(!vis[j.fi]) continue;
        int z=j.fi,wyz=j.se,wxz=vis[z],val=mu[x]*mu[y]*mu[z];
		/*...*/
	  }
	}
	for(auto i:G[x]) vis[i.fi]=0;
  }

这样就可以做到 O(nlnn+mlnm),完全胜利!代码

存在把上面式子化成 O(n2logn) 的做法,简单来说就是只提出 u,对后面枚举的 i,j 都除以 u 去按照之前我们做过的套路完成,但此做法对后面的推导并无意义,具体可以去看第三篇题解。


三倍经验:CF236B Easy Number ChallengeCF235E Number Challenge


P5518 [MtOI2019] 👻乐团 / 莫比乌斯反演基础练习题

东风谷 早苗(Kochiya Sanae)非常喜欢幽灵乐团的演奏,她想对她们的演奏评分。

因为幽灵乐团有 3 个人,所以我们可以用 3 个正整数 A,B,C 来表示出乐团演奏的分数,她们的演奏分数可以表示为

i=1Aj=1Bk=1C(lcm(i,j)gcd(i,k))f(type)

因为音乐在不同的部分会有不同的听觉感受,所以 type 会在 {0,1,2} 中发生变化,其中:

f(0)=1f(1)=i×j×kf(2)=gcd(i,j,k)

因为乐团的歌实在太好听了,导致分数特别高,所以她们的分数要对给定的正整数 p 取模。

因为有很多歌曲要演奏,所以早苗给出了 T 组询问。

1A,B,C105    107p1.05×109    p{prime}    T=70

再来一个三重循环的题。

众所周知,cdqz 机房有且仅有三个👻,它们是:

  • image有名字 的👻,也是👻乐团的团长!

  • image没名字 的👻。

  • image:直接消失的👻,这样的👻常常从你身边飘过!

这三只👻就是 cdqz 机房的真神!/bx


题目名字都告诉你了,还是赶紧来推式子吧。

首先对于 Type = 0/1 是简单的,直接顺着思路往下面推就可以了,也就是这个样子:

对于 Type = 0,我们首先把 lcm 给处理掉再把四个量分离出来就是

i=1Aj=1Bk=1Clcm(i,j)gcd(i,k)=i=1Aj=1Bk=1Cijgcd(i,j)gcd(i,k)=(i=1Ai)BC(j=1Bj)AC1(i=1Aj=1Bgcd(i,j))C(i=1Ak=1Cgcd(i,k))B

前面两项是可以直接用阶乘完成的,也就是说我们只需要求

f(n,m)=i=1nj=1mgcd(i,j)=d=1min(n,m)di=1nj=1m[gcd(i,j)=d]=d=1min(n,m)di=1ndj=1md[gcd(i,j)=1]=d=1min(n,m)di=1ndj=1mdti,tjμ(t)=d=1min(n,m)dt=1min(nd,md)μ(t)ntdmtd

这个时候你可以把上面的指数部分单独提出来用一个函数完成,这样就可以做到线性,是可以过的,也就是后面代码1给出的(把三个 Type 分开了写的)。

但是你推到后面会发现这其实也是 Type = 2 的子问题,而这个式子是可以 O(n) 解决的,所以还是再推一步,这一步也是比较显然的,就是你把 t 提下来再用 T 代替 td

f(n,m)=d=1min(n,m)dt=1min(nd,md)μ(t)ntdmtd=d=1min(n,m)t=1min(n,m)dμ(t)ntdmtd=T=1min(n,m)(dTdμ(Td))nTmT

而中间那一块是可以直接用 O(nlogn) 的时间复杂度预处理出来的(直接暴力枚举),所以单次求就是 O(n)

恭喜你,获得了 20pts 的高分!代码


现在我们来研究 Type = 1,用同样的思路,写出来的式子也是简单的

i=1Aj=1Bk=1C(ijgcd(i,j)gcd(i,k))ijk=(i=1Aiij=1Bk=1Cjk)(j=1Bjji=1Ak=1Cik)1(i=1Aj=1Bgcd(i,j)ijk=1Ck)(i=1Ak=1Cgcd(i,k)ikj=1Bj)

把前面两项提出来就是形如

(i=1Aii)(j=1Bj)(k=1Ck)

预处理一下 i=1nii 可以直接用快速幂求出。

而对于后面两项,也就是求

i=1nj=1mgcd(i,j)ij

这个东西推导方式就较为类似了,笔者并没有把它推导 O(n),而是把指数单独拿出来处理了。

=d=1min(n,m)di=1nj=1m[gcd(i,j)=d]ij=d=1min(n,m)dd2i=1ndj=1md[gcd(i,j)=1]ij

于是可以把指数部分提出来,就变成了求

g(n,m)=i=1nj=1m[gcd(i,j)=1]ij=i=1nj=1mijdi,djμ(d)=d=1min(n,m)μ(d)d2nd(nd+1)2md(md+1)2

然后两次整除分块就可以完成。

很明显和上面 Type = 0 的优化类似,这时可以做到 O(n) 的,但是毕竟瓶颈也不在这里,式子也比较复杂,你直接这样作就好了。

预处理一下 i=1nii2i=1nμ(i)i2 即可,于是你就有 60pts 啦!代码


最后来搞 Type = 2 的情况,按照相同的思路先展开一下

i=1Aj=1Bk=1C(ijgcd(i,j)gcd(i,k))gcd(i,j,k)=(i=1Aij=1Bk=1Cgcd(i,j,k))(j=1Bji=1Ak=1Cgcd(i,j,k))1(i=1Aj=1Bgcd(i,j)k=1Cgcd(i,j,k))(i=1Ak=1Cgcd(i,k)j=1Bgcd(i,j,k))

对于前两项,其实就是(后面的 min 都代表 min(A,B,C)

i=1Aij=1Bk=1Cgcd(i,j,k)=d=1mini=1Ad(id)j=1Bdk=1Cd[gcd(i,j,k)=1]d=d=1mini=1Ad(id)dj=1Bdk=1Cdti,tj,tkμ(t)=d=1mint=1mini=1Atd(itd)dμ(t)BtdCtd

像往常一样,我们直接用 T 代替 td,而后面的 dTdμ(Td) 也就是 idμ=φ,我们就可以得到

=T=1mini=1AT(Ti)φ(T)BTCT

T 提出去就变成了

=(T=1minTφ(T)ATBTCT)(T=1mini=1ATiφ(T)BTCT)

容易发现这两项都可以用整除分块做出来的,稍微预处理一下 φ 的前缀和就可以了。

而对于后面两项,也就是求

i=1Aj=1Bgcd(i,j)k=1Cgcd(i,j,k)

按照之前的经验,我们尝试去枚举 gcd(i,j),令

g(x,n)=i=1ngcd(x,k)=dxφ(d)nd

然后就有

d=1mindg(d,c)i=1Aj=1B[gcd(i,j)=d]

你可以自己尝试推一下,就会发现只能用 O(nlogn) 的时间复杂度完成单次的查询,根本过不了!


那怎么办呢?

式子中还存在一个 gcd,那么我们就尝试去枚举 gcd(i,j,k) 于是式子就变成了:

i=1Aj=1Bgcd(i,j)k=1Cgcd(i,j,k)=d=1mini=1Adj=1Bd(dgcd(i,j))dk=1Cd[gcd(i,j,k)=1]=d=1mini=1Adj=1Bd(dgcd(i,j))dk=1Cdti,tj,tkμ(t)=d=1mint=1mini=1Atdj=1Btd(tdgcd(i,j))dμ(t)Ctd=T=1mini=1ATj=1BT(Tgcd(i,j))φ(T)CT=(T=1minTφ(T)ATBTCT)(T=1mini=1ATj=1BTgcd(i,j)φ(T)CT)

上面的内容和之前推第一部分类似,而现在我们发现其实中间的

i=1ATj=1BTgcd(i,j)

其实就是 Type = 0 中我们推的 f 函数,于是整个式子就变成了

(T=1minTφ(T)ATBTCT)(T=1min(T=1min(AT,BT)(dTdμ(Td))ATTBTT)φ(T)CT)

惊奇地发现这两部分前面的那一块其实是一样的,于是它们就抵消啦!

所以我们需要求的就是

T=1mini=1ATiφ(T)BTCT

T=1min(T=1min(AT,BT)(dTdμ(Td))ATTBTT)φ(T)CT

于是你就可以用两次整除分块线性求出来啦!


这样你就推出了本题的全部式子,写的时候注意细节,在指数上面的东西注意模的是 mod1 而不是 mod,整除分块不要手误了就行。

预处理出一些必要的量是根本不卡常的。代码1代码2


本题存在对于 Type = 2 的情况求 lnexp 回去的做法,具体可以去本题题解区。但笔者还是更喜欢莫反做法。


P3700 [CQOI2017] 小 Q 的表格

为了完成任务,小 Q 需要列一个表格,表格有无穷多行,无穷多列,行和列都从 1 开始标号。为了完成任务,表格里面每个格子都填了一个整数,为了方便描述,小 Q 把第 a 行第 b 列的整数记为 f(a,b)。为了完成任务,这个表格要满足一些条件:

  1. 对任意的正整数 a,b,都要满足 f(a,b)=f(b,a)
  2. 对任意的正整数 a,b,都要满足 b×f(a,a+b)=(a+b)×f(a,b)

为了完成任务,一开始表格里面的数很有规律,第 a 行第 b 列的数恰好等于 a×b,显然一开始是满足上述两个条件的。为了完成任务,小 Q 需要不断的修改表格里面的数,每当修改了一个格子的数之后,为了让表格继续满足上述两个条件,小 Q 还需要把这次修改能够波及到的全部格子里都改为恰当的数。由于某种神奇的力量驱使,已经确保了每一轮修改之后所有格子里的数仍然都是整数。为了完成任务,小 Q 还需要随时获取前 k 行前 k 列这个有限区域内所有数的和是多少,答案可能比较大,只需要算出答案 mod1,000,000,007 之后的结果。

1m1041a,b,kn4×1060x1018

建议盯着式子发呆。


首先,由于 f(a,b)=f(b,a) 所以我们只需要考虑半张表。

而你把第二个式子换一种写法就是

f(a,b)ab=f(a,a+b)a(a+b)

多写几个就变成了

f(a,b)ab=f(a,ka+b)a(ka+b)

那么换一种写法就是

f(a,b)ab=f(a,bmoda)a(bmoda)

我们发现这个东西和辗转相除求 gcd 是一样的,那么我们就可以得到这个很好的性质

f(a,b)ab=f(gcd(a,b),gcd(a,b))gcd(a,b)2

那么

f(a,b)=f(d,d)abd2

于是我们要求的答案其实就是

i=1kj=1kf(i,j)=d=1kf(d,d)i=1kj=1k[gcd(i,j)=d]abd2=d=1kf(d,d)i=1kdj=1kd[gcd(i,j)=1]ij

那么现在就是希望求

g(n)=i=1nj=1n[gcd(i,j)=1]ij

我们需要预处理出所有的 g(n) 才能在查询时以高效的方法完成。


但是按照上一道题我们推式子的方法,发现单次是 n 的,根本过不了!

这时我们考虑在 SP5971 中求的东西

i=1n[gcd(i,n)=1]i=n(φ(n)+ϵ(n))2

带进去就是

g(n)=i=1nj=1n[gcd(i,j)=1]ij=2i=1nj=1i[gcd(i,j)=1]ij1=2i=1nii(φ(i)+ϵ(i))21=i=1ni2φ(i)

于是这个东西就可以线性递推出来了,只要我们能够动态维护 f(d,d) 的区间和,那么最后整除分块一下就可以在 O(n) 的时间复杂度内求出来了。


但是我们发现上面所说的 f(d,d) 的区间和需要做到 O(1) 查询,由于 m104,所以我们不难想到用 O(n)O(1) 的分块来维护。

具体每个块每个元素维护块内的前缀和,在每一个块末尾维护块间的前缀和,修改时暴力修改即可。

总时间复杂度 O(mn),这道题为我们引入了一类式子新的推导方式。代码


本文作者:H_W_Y

本文链接:https://www.cnblogs.com/H-W-Y/p/18203764/NumberTheory4

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   H_W_Y  阅读(22)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起