zoukankan      html  css  js  c++  java
  • 莫比乌斯反演

    莫比乌斯反演

    前置知识-OI Wiki

    莫比乌斯函数 (mu)

    [mu(n)= egin{cases} 1&n=1\ 0&n ext{ 含有平方因子}\ (-1)^k&k ext{ 为 }n ext{ 的本质不同质因子个数}\ end{cases} ]

    (x⊥y)

    如果其中一个有平方因子,(mu(x)*mu(y)=0=mu(xy))

    如果两数都不含平方因子,(mu(x)*mu(y)=(-1)^{k_x+k_y}=mu(xy))

    所以 (mu) 是个积性函数。

    性质:

    [sum_{dmid n}mu(d)= egin{cases} 1&n=1\ 0&n eq 1\ end{cases} ]

    证明:

    (n=prodlimits_{i=1}^kp_i^{c_i},n'=prodlimits_{i=1}^kp_i)

    显然有 (sumlimits_{d|n}mu(d)=sumlimits_{d|n'}mu(d)) ,因为枚举平方因子是无意义的。

    那么这等价于在 (k) 个数里面选 0 个 即 (mu(1)) ,贡献是 1,选 1 个,贡献是 -1,选 2 个,贡献是 1 ,选 (t) 个,贡献是 ((-1)^t) ,也就是 (sumlimits_{i=0}^kdbinom{k}{i}(-1)^i=(1-1)^k=[k==0])

    当 k=0 时,n=1。

    于是就有 ([n==1]\,↔\,sum_{d|n}mu(d)) ,那么罪恶的东西要来了...

    我们都知道,莫比乌斯反演最喜欢的就是 gcd,那就可以把 ([gcd(i,j)=1]) 替换为 (sum_{d|gcd(i,j)}mu(d))

    那么就可以:

    [egin{align} &sum_{i=1}^nsum_{j=1}^n[gcd(i,j)=1]\ =&sum_{i=1}^nsum_{j=1}^nsum_{d|gcd(i,j)}mu(d)\ =&sum_{d=1}^nsum_{i=1}^nsum_{j=1}^n[d|i][d|j]mu(d)\ =&sum_{d=1}^nmu(d)sum_{i=1}^{lfloorfrac{n}{d} floor}sum_{j=1}^{lfloorfrac{n}{d} floor}1\ =&sum_{d=1}^nmu(d)lfloorfrac{n}{d} floorlfloorfrac{n}{d} floor end{align} ]

    于是预处理 (mu) ,再每个询问整除分块,就可以做到 (mathcal O(n+Tsqrt{n})) 了。

    莫比乌斯反演

    真正的反演。

    (f(n)=sum_{d|n}g(d)\,↔\,g(n)=sum_{d|n}mu(d)f(frac{n}{d})\)

    证明:

    [egin{align} &sum_{d|n}mu(d)f(frac{n}{d})\ =&sum_{d|n}mu(d)sum_{k|frac{n}{d}}g(k)\ =&sum_{k|n}g(k)sum_{d|frac{n}{k}}mu(d)\ =&g(n) end{align} ]

    虽然不会用,但结论就是这样...下面是几道例题。

    [button color="success" icon="" url="https://www.luogu.com.cn/problem/P1447" type="round"]P1447[NOI2010] 能量采集[/button]

    ((n,mleq10^5))

    [egin{align} ans&=sum^n_{i=1}sum^m_{j=1}(2*gcd(i,j)-1)\ &=2*sum^n_{i=1}sum^m_{j=1}gcd(i,j)-n*m\ S&=sum^n_{i=1}sum^m_{j=1}gcd(i,j)\ ans&=2S-n*m end{align} ]

    [egin{align} f(d)&=sum^n_{i=1}sum^m_{j=1}[gcd(i,j)=d]\ &=sum^{lfloorfrac{n}{d} floor}_{i=1}sum^{lfloorfrac{m}{d} floor}_{j=1}[gcd(i,j)=1]\ &=sum_{d'}mu(d')sum_{i=1}^{lfloorfrac{n}{d} floor}[d'|i]sum_{j=1}^{lfloorfrac{m}{d} floor}[d'|j]\ &=sum_{d'}mu(d')lfloorfrac{n}{dd'} floorlfloorfrac{m}{dd'} floor end{align} ]

    [egin{align} S&=sum_{d}f(d)*d\ &=sum_{d=1}^nd*sum_{d'=1}^{lfloorfrac{n}{d} floor}mu(d')lfloorfrac{n}{dd'} floorlfloorfrac{m}{dd'} floor\ end{align}\ ]

    (S) 时两段数论分块,可以做到 (O(sqrt{n}*sqrt{n})=O(n)) ,但 (T) 组数据时总时间复杂度达到 (O(n+Tn)),不太优秀。

    对于求(sum^n_{i=1}sum^m_{j=1}gcd(i,j)),其实还有另一种更高效的方法。

    证明:(sum_{d|n}phi(d)=n)

    (f(n)=sum_{d|n}phi(d))

    (a⊥b) ,则 (phi(a)*phi(b)=phi(ab)),那么

    [egin{align} &f(a)*f(b)\ =&sum_{i|a}phi(i)sum_{j|b}phi(b)\ =&sum_{i|a}sum_{j|b}phi(i)*phi(j)\ =&sum_{i|a}sum_{j|b}phi(i*j)\ =&sum_{d|ab}phi(d)\ =&f(ab) end{align} ]

    (f) 也是积性函数,那么

    [egin{align} &f(p^k)\ =&sum_{i=0}^kphi(p^i)\ =&1+(p-1)+(p^2-p)+...+(p^k-p^{k-1})\ =&p^k end{align} ]

    于是设 (n=prod_{i=1}^mp_i^{k_i})(f(n)=prod_{i=1}^mf(p_i^{k_i})=prod_{i=1}^mp_i^{k_i}=n)

    证毕。

    回到求 (sum^n_{i=1}sum^m_{j=1}gcd(i,j)) 身上,把 (gcd(i,j)) 换成 (f(gcd(i,j))) ,那么

    [egin{align} &sum^n_{i=1}sum^m_{j=1}gcd(i,j)\ =&sum^n_{i=1}sum^m_{j=1}sum_{d|gcd(i,j)}phi(d)\ =&sum_dphi(d)sum_{i=1}^n[d|i]sum_{j=1}^m[d|j]\ =&sum_dphi(d)lfloorfrac{n}{d} floorlfloorfrac{m}{d} floor end{align} ]

    这样虽然单次询问需要线性筛 (phi) ,时间复杂度 (O(n+sqrt{n}))

    但在 (T) 组数据时可以做到 (O(n+Tsqrt{n})),比上面方法的 (O(n+Tn)) 更优。

    利用了欧拉函数 (sum_{d|n}phi(d)=n) 的性质,也称这种方法叫欧拉反演。

    [button color="success" icon="" url="https://www.luogu.com.cn/problem/P6222" type="round"]P6222 「P6156 简单题」加强版[/button]

    (T) 组数据,求

    [sum^n_{i=1}sum_{j=1}^n(i+j)^Kmu^2(gcd(i,j))gcd(i,j) ]

    ((T=10^4,nleq10^7))

    [egin{align} &sum_dmu^2(d)* d*sum_{i=1}^nsum_{j=1}^n(i+j)^K[gcd(i,j)=d]\ =&sum_dmu^2(d)*d*d^K*sum_{i=1}^{lfloorfrac{n}{d} floor}sum_{j=1}^{lfloorfrac{n}{d} floor}(i+j)^K[gcd(i,j)=1]\ =&sum_dmu^2(d)*d*d^K*sum_{d'}mu(d')d'^Ksum_{i=1}^{lfloorfrac{n}{dd'} floor}sum_{j=1}^{lfloorfrac{n}{dd'} floor}(i+j)^K\ =&sum_TT^Ksum_{d|T}mu^2(d)*mu(frac{T}{d})*d*sum_{i=1}^{lfloorfrac{n}{T} floor}sum_{j=1}^{lfloorfrac{n}{T} floor}(i+j)^K\ &设\, S(n)=sum_{i=1}^{n}sum_{j=1}^{n}(i+j)^K\ &显然有\, S_n=sum_{s=2}^n(s-1)*s^K+sum_{s=n+1}^{2n}(2n-s+1)*s^K\ &线性筛预处理完全积性函数quad p_n=n^k\,并记录前缀和,那么就可以线性预处理出S_n\ &设\, f_n=sum_{d|n}mu^2(d)mu(frac{n}{d})*d,是积性函数可以线性筛\ 上式=&sum_Tf(T)T^KS(lfloorfrac{n}{T} floor)\ &f(T)T^K可以做前缀和,后面的整除分块\ &O(n+Tsqrt{n}) end{align}]

    个人博客地址: www.moyujiang.com 或 moyujiang.top
  • 相关阅读:
    linux动态库加载路径修改
    RAII手法封装互斥锁
    比特数组
    c++行事准则
    构造函数初始化列表
    this与const
    不完全类型
    Django初学习(四):模板-上下文管理器的使用
    Django初学习(三):模板的使用
    Django初学习(二):路由&子路由
  • 原文地址:https://www.cnblogs.com/moyujiang/p/14890906.html
Copyright © 2011-2022 走看看