• 莫比乌斯反演学习笔记


    0.前置知识

    一些函数

    1. (1(n)=1)
    2. (id(n)=n)
    3. (sigma(n))(n)的约数和

    狄利克雷卷积

    定义两个数论函数运算(*)

    (h=f*g),则

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

    它满足一些性质:

    1. (f*g=g*f)

    2. (f*(g*h)=(f*g)*h)

      因为(sum_{(ij)k=n}(f(i)g(j))h(k)=sum_{i(jk)=n}f(i)(g(j)h(k)))

    3. ((f+g)*h=f*h+g*h)

    4. ((xf)*g=x(f*g))

    5. 设单位元(epsilon(n) = [n = 1]),则(epsilon*f=f)

    6. 对于每个(f(1) eq 0)的函数(f),存在逆元(g)使得(f*g=epsilon)

    如何求一个函数的逆元呢?

    (g(n))满足以下式子:

    [g(n)=frac 1{f(1)}left(epsilon(n)-sum_{i|n,i eq1}f(i)g(frac ni) ight) ]

    这样的话:

    [sum_{i|n}f(i)g(frac ni) \ =f(1)g(n) + sum_{i|n, i eq 1} f(i)g(frac ni) \ =epsilon(n) \ herefore f*g=epsilon ]

    1.莫比乌斯反演

    定义一个函数(mu)使得(mu*1=epsilon)

    这样的话,如果(g*1=f),则(f*mu=g)

    即:如果(f(n)=sum_{d|n}g(d)),则(g(n)=sum_{d|n}mu(d)f(frac nd))

    是不是很简单

    2.题目

    (n<m)求:

    #1

    [sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=1] ]

    (f=epsilon)(ecause epsilon=1*mu,; herefore g=mu)

    于是原式变为:

    [sum_{i=1}^nsum_{j=1}^msum_{d|i,d|j}mu(d) \ =sum_{d=1}^n mu(d)sum_{i=1}^nsum_{j=1}^m[d|i][d|j] \ =sum_{d=1}^n mu(d)left[frac nd ight]left[frac md ight] ]

    预处理(mu),数论分块就可以(O(sqrt n))求了

    #2

    [sum_{i=1}^nsum_{j=1}^m gcd(i,j) ]

    (f=id)(ecause id=1*varphi,; herefore g=varphi)

    于是原式变为:

    [sum_{d=1}^nvarphi(d)left[frac nd ight]left[frac md ight] ]

    #3

    [sum_{i=1}^nsum_{j=1}^msigma(gcd(i,j)) ]

    (f=sigma)(ecausesigma=1*(mu*sigma),; herefore g=mu*sigma)

    于是原式变为:

    [sum_{d=1}^ng(d)left[frac nd ight]left[frac md ight] ]

    因为积性函数可以线性筛,所以也可以预处理

    #4

    [sum_{i=1}^nsum_{j=1}^mf(gcd(i,j)) ]

    (g=mu*f),如果我们能预处理出(f),那么可以这样求(g)

    (当然是蒯的啦)

    void get_g_1(int N, const int *f, int *g)
    {
    	for (int i = 1; i <= N; i++) g[i] = 0;
    	for (int i = 1; i <= N; i++)
    		for (int j = 1; i * j <= N; j++)
    			g[i * j] = (g[i * j] + mu[i] * f[j]) % mod;
    } // 依照定义,O(nlogn)
    
    void get_g_2(int N, const int *f, int *g)
    {
    	for (int i = 1; i <= N; i++) g[i] = f[i];
    	for (int i = 1; i <= N; i++)
    		for (int j = 2; i * j <= N; j++)
    			g[i * j] = (g[i * j] - g[i]) % mod;
    } // 类似求狄利克雷卷积逆的方式,不需要线性筛 mu ,O(nlogn)
    
    void get_g_3(int N, const int *f, int *g)
    {
    	for (int i = 1; i <= N; i++) g[i] = f[i];
    	for (int i = 0; i < prime_count; i++)
    		for (int j = N / prime[i]; j >= 1; j--)
    			g[j * prime[i]] = (g[j * prime[i]] - g[j]) % mod;
    } // Magic! O(nloglogn)
    

    于是原式变为:

    [sum_{d=1}^ng(d)left[frac nd ight]left[frac md ight] ]

  • 相关阅读:
    个人工作量
    个人作业
    本周psp
    典型用户和场景总结
    排球比赛计分规则功能说明书
    我与计算机
    个人作业
    《怎样成为一个高手》读后感
    第十八周个人作业
    第十六周 项目耗时记录
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/10182999.html
Copyright © 2020-2023  润新知