zoukankan      html  css  js  c++  java
  • 积性函数的整理

    定义

    如果一个数论函数(f(n))满足

    [f(pq)=f(p)f(q),pperp q ]

    则称(f(n))是一个积性函数。

    特别的,如果不要求(pperp q)且依然满足上述式子的话,则称(f(n))是一个完全积性函数。

    简单约定

    ((i,j))表示(gcd(i,j))

    ([a])表示一个条件判断函数,当(a)为真是([a]=1),否则([a]=0)

    (iperp j)表示((i,j)==1)

    狄利克雷卷积懒得打括号了。

    常见积性函数

    [e(n)=[n=1] ]

    [1(n)=1 ]

    [mu(n)=egin{cases}(-1)^k&n=p_1p_2p_3dots p_k\0&n=p^2qend{cases} ]

    [varphi(n)=sum_{i=1}^n[iperp n] ]

    [d(n)=sum_{i|n}1 ]

    [id(n)=n ]

    [sigma(n)=sum_{d|n}d ]

    至于它们为什么是积性函数,,,,

    我也管不了那么多了。

    狄利克雷卷积

    定义

    [f*g(n)=sum_{d|n}f(d)g(frac nd) ]

    要计算的话可以把枚举约数换成枚举倍数(下面会讲到),以调和级数(O(nlogn))的复杂度求出(f*g)的前(n)项。

    交换律

    [f*g(n)=sum_{d|n}f(d)g(frac nd)=sum_{d|n}g(d)f(frac nd)=g*f(n) ]

    结合律

    [f*g*h(n)=sum_{d|n}f(d)sum_{t|frac nd}g(t)h(frac n{dt})=sum_{d_1d_2d_3=n}f(d_1)g(d_2)h(d_3)=f*(g*h)(n) ]

    常见积性函数的卷积

    [forall f(n),e*f(n)=f(n) ]

    [1*1(n)=sum_{d|n}1=d(n) ]

    [id*1(n)=sum_{d|n}d=sigma(n) ]

    [mu*1(n)=sum_{d|n}mu(d)=[n=1]=e(n) ]

    这个需要特别说明一下。

    假设(n=p_1^{k_1}p_2^{k_2}dots p_m^{k_m}),那么上式可以改写成:

    [mu*1(n)=sum_{c_1=0}^{k_1}sum_{c_2=0}^{k_2}dotssum_{c_m=0}^{k_m}mu(p_1^{c_1}p_2^{c_2}dots p_m^{c_m}) ]

    观察(mu(n))的定义,可以发现它与(n)的质因子个数有关,而且当某个质因子出现不止一次时,(mu(n)=0)。这样的话,只要(c_1)(c_n)中有任意一个大于(1),后面那个(mu)值就为(0)

    这样的话,我们就可以大大降低枚举范围:

    [mu*1(n)=sum_{c_1=0}^1sum_{c_2=0}^1dotssum_{c_m=0}^1mu(p_1^{c_1}p_2^{c_2}dots p_m^{c_m}) ]

    [=sum_{c_1=0}^1sum_{c_2=0}^1dotssum_{c_m=0}^1(-1)^{sum_{i=1}^mc_i} ]

    [=sum_{i=0}^m(-1)^idbinom mi ]

    [=[m=0]=[n=1]=e(n) ]

    至于最后那个式子为什么是([m=0]),证法多种多样,这里不再赘述。

    那么继续:

    [varphi*1(n)=sum_{d|n}varphi(d)=n=id(n) ]

    这个又是为什么?

    直接证比较麻烦,我们利用(mu*1=e)证一个反过来的式子:

    [varphi(n)=id*mu(n) ]

    直接暴力拆式子即可。要用到下面讲到的一些技巧,可以回头再来看。

    [varphi(n)=sum_{i=1}^n[iperp n] ]

    [=sum_{i=1}^n[(i,n)==1] ]

    [=sum_{i=1}^nsum_{d|(i,n)}mu(d) ]

    [=sum_{d|n}mu(d)frac nd ]

    [=id*mu(n) ]

    这样,我们就完成了上述积性函数的大一统:

    [muxrightarrow{*1}exrightarrow{*1}1xrightarrow{*1}d ]

    [varphixrightarrow{*1}idxrightarrow{*1}sigma ]

    反过来也可以:

    [muxleftarrow{*mu}exleftarrow{*mu}1xleftarrow{*mu}d ]

    [varphixleftarrow{*mu}idxleftarrow{*mu}sigma ]

    莫比乌斯反演

    类似于二项式反演和斯特林反演,有一个这样的反演式子:

    [f(n)=sum_{d|n}g(d)iff g(n)=sum_{d|n}mu(frac nd)f(d) ]

    其实没毛用,因为它的本质就是这样的:

    [f=g*1iff g=mu*f ]

    但这样看的话,似乎就是废话了。

    常用推式子技巧

    无关项提前

    本质是分配律。

    [sum_{i=1}^nsum_{j=1}^ma_ib_j=sum_{i=1}^na_isum_{j=1}^mb_j ]

    交换枚举顺序

    [sum_{i=1}^na_isum_{j=1}^mb_j=sum_{j=1}^mb_jsum_{i=1}^na_i ]

    这个看上去还是很(naive)

    比较重要的是枚举约数变成枚举倍数:

    [sum_{i=1}^na_isum_{d|i}b_d=sum_{d=1}^nb_dsum_{i=1}^{lfloorfrac nd floor}a_{id} ]

    反演

    就是活用上面那几个常用积性函数的狄利克雷卷积关系式,尤其是(mu*1=e)

    算法

    数论分块

    这个居然在我很(naive)的时候自己(yy)出来了。

    举个例子,求(sum_{i=0}^nlfloorfrac ni floor,nleq10^9)

    不会的话打个表,然后就会了

    (n=100)时,可以发现(lfloorfrac n{100} floor,lfloorfrac n{99} floor,dots,lfloorfrac n{51} floor)都是(1)(lfloorfrac n{50} floor,lfloorfrac n{49} floor,dots,lfloorfrac n{34} floor)都是(2),这样的话,我们得到了一个可靠的结论:

    (lfloorfrac n{lfloorfrac ni floor+1} floor,lfloorfrac n{lfloorfrac ni floor+2} floor,dots,lfloorfrac n{lfloorfrac n{i+1} floor} floor)的结果都是(i+1)

    这样我们就得到了一个快速的根号算法:

    对于大于(sqrt n)的数,不同的(lfloorfrac ni floor)只有(sqrt n)个;

    小于(sqrt n)的数只有(sqrt n)个,直接暴力算即可。

    线性筛

    这个比较简单,只要我们探究出(f(p^k))的表达式,就可以线性筛出所有(f(i))

    杜教筛

    假如我们要求(s(n)=sum_{i=1}^nf(i)),如果我们能够找到另一个函数(g(n))使得(g(n))(f*g(n))都比较好求,我们就可以利用杜教筛。

    具体过程是这样的:

    [sum_{i=1}^nf*g(i)=sum_{i=1}^nsum_{d|i}f(frac id)g(d) ]

    [=sum_{d=1}^ng(d)sum_{i=1}^{lfloorfrac nd floor}f(i) ]

    [=sum_{d=1}^ng(d)s(lfloorfrac nd floor) ]

    (d=1)时,(s(lfloorfrac nd floor))就是(s(n)),所以有

    [s(n)=sum_{d=1}^ng(d)s(lfloorfrac nd floor)-sum_{d=2}^ng(d)s(lfloorfrac nd floor) ]

    [=sum_{i=1}^nf*g(i)-sum_{d=2}^ng(d)s(lfloorfrac nd floor) ]

    这样,如果我们能够快速求出(sum_{i=1}^nf*g(i))(g(d)),我们就可以对右边数论分块进行递归求解。我们可以用线性筛筛出前面一部分来优化复杂度。

    复杂度是(O(n^{frac23})),证明并不会,可以参考这个

    (min\_25)

    不会。

    留着坑吧,没准哪天会了

    不过也要退役了

    应用

    1、求(sum_{i=1}^nsum_{j=1}^m[iperp j],n,mleq10^9)

    需要用到的东西上面已经全部给出了。要注意([iperp j])其实就是(e((i,j)))

    [sum_{i=1}^nsum_{j=1}^msum_{d|(i,j)}mu(d) ]

    [=sum_{d=1}^nmu(d)sum_{i=1}^{lfloorfrac nd floor}sum_{j=1}^{lfloorfrac md floor}1 ]

    [=sum_{d=1}^nmu(d)lfloorfrac nd floorlfloorfrac md floor ]

    数论分块套上杜教筛求出(summu(d))即可。

    杜教筛(mu)的话,令函数(g)(1)函数,此时(sum_{i=1}^nmu*1(i)=1)(1)函数本身也没有任何难度可言。

    2、求(sum_{i=1}^nsum_{j=1}^m(i,j),n,mleq10^9)

    同样的,因为((i,j))就是(id((i,j))),所以套用上一题做法即可。

    [sum_{i=1}^nsum_{j=1}^msum_{d|(i,j)}varphi(d) ]

    [=sum_{d=1}^nvarphi(d)lfloorfrac nd floorlfloorfrac md floor ]

    杜教筛(varphi)的话,我们同样令(g)(1)函数,此时(sum_{i=1}^nvarphi*1(i)=frac{n(n+1)}2)

    3、给出一个(n*m)的点阵,如果一对点连成的线段不经过其它点,那么称这对点是合法的。求有多少合法的点对。

    这是我原创的一道蠢题……做法就交给各位神仙了。

    ……

    备注

    给出一些可能用到的链接:

    模板

    杜教筛

    例题

    例题1

    例题2(人生第一道紫题,自己yy出了一个(O(nsqrt n))的做法,现在看起来好(low)啊)

    例题3(数据有误)

  • 相关阅读:
    水晶报表关于System.Web.Extensions报错的问题
    个人下一步学习计划
    一个老程序员对数据库的一点纠结
    Visual SourceSafe权限配置记录
    SQL SERVER 2008代码折叠小技巧
    用命令行自动备份数据库到其他服务器
    CrystalReports 2008序列号留档
    ····
    C语言中的static
    页面自动刷新的几种方法
  • 原文地址:https://www.cnblogs.com/star-city/p/11101991.html
Copyright © 2011-2022 走看看