zoukankan      html  css  js  c++  java
  • 莫比乌斯反演入门解析

    以下教程前半部分来自B站电子科技大学的视频 https://www.bilibili.com/video/av43470417?from=search&seid=9275043167445755699。菜鸡如我就还没看懂。

    分割线后半部分教程来自 https://www.luogu.org/blog/An-Amazing-Blog/mu-bi-wu-si-fan-yan-ji-ge-ji-miao-di-dong-xi

    教程一

    问题引入

    给定整数 N 和 M 。求满足 (1 leq x leq N, 1 leq y leq M)(gcd(x, y)) 为质数的点对 ((x, y)) 的个数。

    数据范围: (1 leq N,M leq 1000000)

    莫比乌斯(Mobius)函数:

    [mu(x) = egin{cases} 1 & ext{: } x = 1 \ -1 & ext{: } x = p_1p_2...p_k(p_i为不相同质数) \ 0 & ext{: 其他情况} end{cases} ]

    线性筛

    int prime[maxn], prime_tot;
    bool prime_tag[maxn];
    int mu[maxn];
    void pre_calc(int lim) {
    	mu[1] = 1;
    	for(int i = 2; i <= lim; i++) {
    		if(!prime_tag[i]) {
    			prime[++prime_tot] = i;
    			mu[i] = -1;
    		}
    		for(int j = 1; j <= prime_tot; j++) {
    			if(i*prime[j] > lim) {
    				break;
    			}
    			prime_tag[i*prime[j]] = true;
    			if(i % prime[j] == 0) {
    				mu[i*prime[j]] = 0;
    				break;
    			}
    			else {
    				mu[i*prime[j]] = -mu[i];
    			}
    		}
    	}
    }
    

    狄利克雷卷积

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

    积性函数

    积性函数:指对于所有互质的整数 a 和 b 有 (f(ab)=f(a)f(b)) 的数论。

    • 欧拉函数(varphi(n))
    • 莫比乌斯函数(mu(n))
    • 单位函数:(Id(n) = n)
    • 不变函数:(1(n) = 1)
    • 幂函数:(Idk(n) = n^k)
    • 因子个数函数:(d(n), d = 1*1)
    • 因子和函数:(sigma(n), sigma = 1 * Id)
    • 因子函数:(sigma k(n))
    • 狄利克雷卷积单位元(varepsilon = [n == 1])

    莫比乌斯反演

    [g(n) = sum_{d|n}f(d) ightarrow f(n) = sum_{d|n} mu(d)g(frac{n}{d}) \ g(n) = sum_{n|d}f(d) ightarrow f(n) = sum_{n|d} mu(frac{d}{n})g(d) ]

    证明一

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

    证明二

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

    解决问题

    (sum_{1leq i leq N} sum_{1 leq j leq M}[gcd(i, j) == p]),p是质数

    [f(p) = sum_{1leq i leq N} sum_{1 leq j leq M}[gcd(i, j) == p] ]

    [g(p) = sum_{1leq i leq N} sum_{1 leq j leq M}[p | gcd(i, j)] ]

    那么,

    [g(n) = sum_{n|d}f(d) 且有 g(n) = lfloor{frac{N}{n}} floor lfloor{frac{M}{n}} floor ]

    [f(n) = sum_{n|d} mu(frac{d}{n})g(d) = sum_{n|d} mu(frac{d}{n}) lfloor{frac{N}{d}} floor lfloor{frac{M}{d}} floor ]

    [egin{aligned} ans &= sum_{n in prime} sum_{n|d} mu(frac{d}{n}) lfloor{frac{N}{d}} floor lfloor{frac{M}{d}} floor \ &= sum_{n in prime} sum_{t} mu(t) lfloor{frac{N}{nt}} floor lfloor{frac{M}{nt}} floor (t := d/n) \ &= sum_{1 leq k leq min(N,M)} lfloor{frac{N}{k}} floor lfloor{frac{M}{k}} floor sum_{n|k,n in prime} mu(frac{k}{n}) (k := nt) end{aligned} ]

    [sum(k) := sum_{n|k,n in prime} mu(frac{k}{n}) 可以预处理 ]

    for(int i = 1; i <= prime_tot; i++) {
    	for(int j = 1; prime[i] * j <= up; j++) {
    		sum[prime[i] * j] += mu[j];
    	}
    }
    

    [ans = = sum_{1 leq k leq min(N,M)} lfloor{frac{N}{k}} floor lfloor{frac{M}{k}} floor sum(k) ]

    整除分块

    (lfloor frac{N}{k} floor(1 leq k leq N)) 有约 (2sqrt{N}) 个可能值。快速计算 (sum_{}lfloor frac{N}{k} floor) 的方法:

    for(int l = 1; l <= N; l = r+1) {
    	r = N / (N/l);
    	ans += (r-l+1) * (N/l);
    }
    

    杜教筛

    (sum^{n}_{i=1}mu(i),n leq 10^{12})

    [M(n) := sum^{n}_{i=1}mu(i) ]

    [1 = sum^{n}_{i=1}varepsilon(i) = sum^{n}_{i=1}sum_{d|i}mu(d) = sum^{n}_{i=1}sum^{lfloor frac{n}{i} floor}_{j=1}u(j) = sum^{n}_{i=1}M(lfloor frac{n}{i} floor) ]

    [M(n) = 1 - sum^{n}_{i=2}M(lfloor frac{n}{i} floor) ]

    int mu_sum[maxn];
    unordered_map<long long, int> mp;
    
    int mu_calc(long long n) {
    	if(n < lim) {
    		return mu_sum[n];
    	}
    	if(mp.count(n)) {
    		return mp[n];
    	}
    	int ret = 1;
    	for(long long l = 2, r; l <= n; l = r+1) {
    		r = n / (n/l);
    		ret -= (r-l+1) * mu_calc(n/l);
    	}
    	return mp[n] = ret;
    }
    


    教程二

    先记住

    [[gcd(i,j) == 1] = sum_{d|gcd(i, j)} mu(d) ]

    问题 #1

    [sum^{n}_{i=1} sum^{m}_{j=1} [gcd(i, j) == 1] , (n < m) ]

    解法

    [原式 = sum^{n}_{i=1} sum^{m}_{j=1} sum_{d|gcd(i, j)} mu(d) ]

    然后枚举 (d) ,显然有 (din(1,n) [d | gcd(i,j)]) ,于是将 (d) 提到前面去,则 (i、j) 都是 (d) 的倍数,化简得:

    [原式 = sum^{n}_{d=1} mu(d) * lfloor frac{n}{d} floor * lfloor frac{m}{d} floor ]

    后面的两个除法可以用上面攻略里的整除分块进行 (o(sqrt{n})) 复杂度的求解,当然也可以跑 (o(n))

    问题 #2

    [sum^{n}_{i=1} sum^{m}_{j=1} [gcd(i, j) == k] , (n < m) ]

    解法

    和上一题很像对吧,同时除以 k:

    [原式 = sum^{lfloor frac{n}{k} floor}_{i=1} sum^{lfloor frac{m}{k} floor}_{j=1} [gcd(i, j) == 1] ]

    之后就一模一样了。

    问题 #3

    [sum^{n}_{i=1} sum^{m}_{j=1} ij[gcd(i, j) == k] , (n < m) ]

    解法

    也是同时除以 k :

    [原式 = sum^{lfloor frac{n}{k} floor}_{i=1} sum^{lfloor frac{m}{k} floor}_{j=1} ij[gcd(i, j) == 1] * k^2 ]

    因为式子中 (i、j) 也被除了 k,需要在末尾补回来。

    [egin{aligned} 原式 &= sum^{lfloor frac{n}{kd} floor}_{i=1} sum^{lfloor frac{m}{kd} floor}_{j=1} ij sum_{d|gcd(i,j)}mu(d) * k^2 \ &= sum^{lfloor frac{n}{k} floor}_{d=1} mu(d) * d^2 sum^{lfloor frac{n}{kd} floor}_{i=1} sum^{lfloor frac{m}{kd} floor}_{j=1} ij * k^2 \ &= k^2 * sum^{lfloor frac{n}{k} floor}_{d=1} mu(d) * d^2 sum^{lfloor frac{n}{kd} floor}_{i=1} isum^{lfloor frac{m}{kd} floor}_{j=1} j end{aligned} ]

    然后就发现后两项是个等差数列,也能在复杂度 (o(sqrt{n})) 下求出。

    问题 #4

    [sum^{n}_{i=1} sum^{m}_{j=1} lcm(i, j) ]

    解法

    首先: (lcm(i,j) = frac{i*j}{gcd(i, j)}),那么:

    [egin{aligned} 原式 &= sum^{n}_{d=1}sum^{n}_{i=1} sum^{m}_{j=1} frac{i*j}{d} * [gcd(i, j) == d] (同时除d)\ &= sum^{n}_{d=1}sum^{lfloor frac{n}{d} floor}_{i=1} sum^{lfloor frac{m}{d} floor}_{j=1} i*j*d * [gcd(i, j) == 1] \ &= sum^{n}_{d=1}sum^{lfloor frac{n}{d} floor}_{i=1} sum^{lfloor frac{m}{d} floor}_{j=1} i*j*d sum_{k|gcd(i,j)} mu(k) (枚举k)\ &= sum^{n}_{d=1}d sum^{lfloor frac{n}{d} floor}_{k=1} mu(k)*k^2 sum^{lfloor frac{n}{dk} floor}_{i=1}isum^{lfloor frac{n}{dk} floor}_{j=1}j end{aligned} ]

    此时已经 (o(n)) 了,(lfloor frac{n}{d} floor) 可以分一次块,(lfloor frac{n}{dk} floor) 也可以分一次。所以是 (o(n))

    后面原作者给出了更优解,我这里懒得贴过程了。也懒得记了。超出我承受范围了。

    问题 #5

    [sum^{n}_{i=1} sum^{m}_{j=1} d(i*j) ]

    其中,(d(i, j)) 表示 (i*j) 的约数个数。

    解法

    拿出小本本记个公式:

    [d(i*j) = sum_{x|i} sum_{y|j} [gcd(x,y) == 1] ]

    怎么证明的,我不想知道...请移步原作者博客。



    虽然我什么都还不会

    就先这样好了,下班了QAQ。

  • 相关阅读:
    前端3
    前端-1
    第三十七章 MYSQL(二)
    第三十六章 MYSQL语句(一)
    第三十五 MYSQL 语句
    数字转换成中文大小写、金额大小写
    NPOI随笔——图片在单元格等比缩放且居中显示
    NPOI随笔——单元格样式CellStyle问题
    C++、C#、VB各语言日志代码
    .NET认识与理论总结
  • 原文地址:https://www.cnblogs.com/Decray/p/11215469.html
Copyright © 2011-2022 走看看