莫比乌斯反演

狄利克雷卷积

f, g 为数论函数

h=fg, 即 h(n)=d1d2=nf(d1)g(d2)

性质

  1. 满足交换律

  2. 满足结合律,即 p(n)=(fg)h=f(gh)=d1d2d3=nf(d1)g(d2)h(d3)

  3. f,g 是积性函数,则 fg 是积性函数(完全积性函数不满足此条性质)

常见卷积:

  1. 1μ=e
  2. fe=f
  3. idμ=ϕ

莫比乌斯反演

f=g1g=fμ

f(n)=dng(d)g(n)=dnf(d)μ(nd)

证明:

引理1:1μ=e

引理2:fe=f

  1. f=g1 , 两边同时卷上 μ

    fμ=g1μ=g(1μ)=ge=g

  2. g=fμ, 两边同时卷上 1

    g1=fμ1=f(μ1)=fe=f

引理1,2 暴力带入狄利克雷卷积并利用积性函数的性质(两个积性函数卷起来仍是积性函数)即可证明

莫比乌斯反演 - 题目 - Daimayuan Online Judge

f=g1, 因此 g=fμ, 线性筛求出 μ

g(i) 的过程可考虑每个因子对 g(i) 的贡献,因此可以:

for (int d1 = 1; d1 <= n; d1++)
    	for (int d2 = 1; d1 *d2 <= n; d2++)
    		g[d1*d2] += f[d1] * mu[d2];

由调和级数,复杂度为 O(nlogn)

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
const int N = 1e6 + 10;

uint n;
uint pr[N/5], p[N], cnt, mu[N], f[N], g[N];

unsigned int A,B,C;
inline unsigned int rng61()
{
    A ^= A << 16;
    A ^= A >> 5;
    A ^= A << 1;
    unsigned int t = A;
    A = B;
    B = C;
    C ^= t ^ A;
    return C;
}

void get_primes(uint n)
{
	p[1] = 1, mu[1] = 1;
	for (int i = 2; i <= n; i++)
	{
		if (!p[i])
		{
			p[i] = i;
			mu[i] = -1;
			pr[++cnt] = i;
		}
		for (int j = 1; j <= cnt && pr[j] <= n / i; j++)
		{
			p[i*pr[j]] = pr[j];
			if (p[i] == pr[j])
			{
				mu[i*pr[j]] = 0;
				break;
			}
			mu[i*pr[j]] = -mu[i];
		}
	}
}
int main()
{
    scanf("%d%u%u%u", &n, &A, &B, &C);
    for (int i = 1; i <= n; i++)
        f[i] = rng61();
    get_primes(n);
    for (int d1 = 1; d1 <= n; d1++)
    	for (int d2 = 1; d1 *d2 <= n; d2++)
    		g[d1*d2] += f[d1] * mu[d2];
	uint ans = 0;
    for (int i = 1; i <= n; i++) ans ^= g[i];
    printf("%u\n", ans);
    return 0;
}

互质数对 - 题目 - Daimayuan Online Judge

T(1<=T<=1000) 组询问,每次给出 n,m(1<=n,m<=107), 求 满足 1<=i<=n,1<=j<=mgcd(i,j)=1 的对数

i=1nj=1mgcd(i,j)==1i=1nj=1me(gcd(i,j))e=1μi=1nj=1me(gcd(i,j))=i=1nj=1m1μ(gcd(i,j))=i=1nj=1mdgcd(i,j)μ(d)=dgcd(i,j)μ(d)i=1nj=1m1=di,djμ(d)i=1nj=1m1=d=1nμ(d)i=1dinj=1djm1=d=1nμ(d)nimj

因此求出 μ 的前缀和,加上整除分块即可

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;
typedef long long ll;

const int N = 1e7 + 10;

int pr[N/5], p[N], cnt, mu[N], s[N];
void get_primes(int n)
{
	p[1] = mu[1] = s[1] = 1;
	for (int i = 2; i <= n; i++)
	{
		if (!p[i])
			pr[++cnt] = i, p[i] = i, mu[i] = -1;
		for (int j = 1; j <= cnt && pr[j] <= n / i; j++)
		{
			p[i*pr[j]] = pr[j];
			if (p[i] == pr[j])
			{
				mu[i*pr[j]] = 0;
				break;
			}
			mu[i*pr[j]] = -mu[i];
		}
	}
	for (int i = 2; i <= n; i++)
		s[i] = s[i-1] + mu[i];
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	get_primes(N - 10);
	while(T--)
	{
		int n, m;
		cin >> n >> m;
		if (n > m) swap(n, m);
		ll ans = 0;
		for (int l = 1; l <= n; l++)
		{
			int r = min(n / (n / l), m / (m / l));
			ans += (ll)(s[r] - s[l-1]) * (n / l) * (m / l);
			l = r;
		}
		cout << ans << endl;
	}
	return 0;
}

gcd之和 - 题目 - Daimayuan Online Judge

跟上一题类似

形如: i=1nj=1mf(gcd(i,j)) ,可用 g=fμ 找到 g ,再用 f=g1 带入得

i=1nj=1mdgcd(i,j)g(d) = d=1ng(d)nimj

本题中 g=idμ=ϕ

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;
typedef long long ll;

const int N = 1e7 + 10;

int pr[N/5], p[N], cnt, phi[N];
ll s[N];
void get_primes(int n)
{
	p[1] = phi[1] = s[1] = 1;
	for (int i = 2; i <= n; i++)
	{
		if (!p[i])
			pr[++cnt] = i, p[i] = i, phi[i] = i - 1;
		for (int j = 1; j <= cnt && pr[j] <= n / i; j++)
		{
			p[i*pr[j]] = pr[j];
			if (p[i] == pr[j])
			{
				phi[i*pr[j]] = phi[i] * pr[j];
				break;
			}
			phi[i*pr[j]] = phi[i] * (pr[j] - 1);
		}
	}
	for (int i = 2; i <= n; i++)
		s[i] = s[i-1] + phi[i];
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	get_primes(N - 10);
	while(T--)
	{
		int n, m;
		cin >> n >> m;
		if (n > m) swap(n, m);
		ll ans = 0;
		for (int l = 1; l <= n; l++)
		{
			int r = min(n / (n / l), m / (m / l));
			ans += (ll)(s[r] - s[l-1]) * (n / l) * (m / l);
			l = r;
		}
		cout << ans << endl;
	}
	return 0;
}

posted @   hzy0227  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
点击右上角即可分享
微信分享提示