zoukankan      html  css  js  c++  java
  • Dirichlet卷积

    莫比乌斯反演的前置知识

    定义

    (f,g)是数论函数,考虑数论函数(h)满足

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

    则称(h)(f)(g)的狄利克雷卷积,记作(h=f*g),这里的(*)表示卷积。

    比如(h(6)=f(1)*g(6)+f(2)*g(3)+f(3)*g(2)+f(6)*g(1))

    性质

    1. 单位函数(epsilon)是狄利克雷卷积的单位元,即对于任意函数(f),有(epsilon*f=f*epsilon=f)
    2. 狄利克雷卷积满足交换律和结合律。
    3. 如果(f,g)都是积性函数,那么(f*g)也是积性函数。

    许多关系都可以用狄利克雷卷积来表示。

    下面用(1)来表示取值恒为(1)的常函数,定义幂函数( ext{Id}_{k}(n)=n^k, ext{Id=Id}_1)

    除数函数的定义可以写为:

    [sigma_k=1* ext{Id}_k ]

    欧拉函数的性质可以写为:

    [ ext{Id}=varphi*1 ]

    计算狄利克雷卷积

    (f,g)是数论函数,计算(f)(g)的狄利克雷卷积在(n)处的值需要枚举(n)的所有约数。

    如果要计算(f)(g)的狄利克雷卷积的前(n)项,可以枚举(1)(n)中每个数的倍数,根据调和数的相关结论,这样做的复杂度是(O(nlog n))

    求函数的逆

    狄利克雷卷积有一个性质:对每个(f(1) eq0)的函数(f),都存在一个函数(g)使得 (fast g=epsilon)

    那么我们如何求出一个函数的逆呢?

    只需要定义:

    [g(n)=frac 1{ f(1)}left([n=1]-sumlimits_{imid n, i eq1} f(i) gleft(frac ni ight) ight) ]

    这样的话

    [egin{aligned}&quadsum_{imid n} f(i) gleft(frac ni ight)\&= f(1) g(n)+sum_{imid n,i eq1} f(i) gleft(frac ni ight)\&=[n=1]end{aligned} ]

    最后一步直接把(g(n))的定义带进去就好

    [= f(1)*frac{1}{ f(1)}([n = 1] - sumlimits_{i|n,i eq1} f(i) g(frac n i))+ sumlimits_{i|n,i eq1} f(i) g(frac ni) ]

    例题

    P2303 [SDOI2012]Longge的问题

    给定正整数(n),求

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


    枚举( ext{gcd})

    [egin{align*} sum_{i=1}^{n}gcd(i,n) &= sum_{d|n}dsum_{i=1}^{n}[gcd(i,n)=d] \ &= sum_{d|n}dsum_{i=1}^{frac{n}{d}}[gcd(i,frac{n}{d})=1] \ &= sum_{d|n}dvarphi(frac{n}{d}) end{align*}]

    枚举(n)的约数直接求。答案是积性的。

    #include <cmath> 
    #include <cstdio>
    #include <cstring> 
    #include <iostream>
    #define int long long
    using namespace std;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for ( ; !isdigit(c); c = getchar()) if(c == '-') f = -1; 
    	for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, ans;
    
    int euler(int x) {
    	int ans = x, rt = sqrt(x);
    	for (int i = 2; i <= rt; i++) {
    		if (x % i == 0) {
    			ans = ans - ans / i;
    			while (x % i == 0) x /= i;
    		}
    	}
    	if (x > 1) ans = ans - ans / x;
    	return ans;
    }
    
    signed main() {
    	n = read();
    	int x = sqrt(n);
    	for (int i = 1; i <= x; i++) {
    		if (n % i == 0) {
    			ans += euler(n / i) * i;
    			if (i * i != n) ans += euler(i) * (n / i);
    		}
    	}
    	cout << ans << '
    ';
    	return 0;
    }
    
  • 相关阅读:
    委托与事件
    JSON
    JavascriptBoolean运算符
    SQL执行字符串
    ref和out与SQL中的output
    早绑定、晚绑定
    浅复制和深复制
    Android Fragments 详细使用
    Android 两种为自定义组件添加属性的使用方法和区别
    Gallery 3D+倒影 滑动切换图片示例(转)
  • 原文地址:https://www.cnblogs.com/loceaner/p/12785524.html
Copyright © 2011-2022 走看看