一点数论--狄利克雷 / Dirichlet卷积

一、数论函数的定义

数论函数指定义域为正整数集的函数

二、积性函数与完全积性函数

2.1 数论函数的定义
对于一个数论函数 f ( x ) f(x) f(x) 满足 f ( a b ) = f ( a ) × f ( b ) f(ab) = f(a) × f(b) f(ab)=f(a)×f(b),则称 f ( x ) f(x) f(x) 为一个积性函数

∀ a , b ∈ Z + ∀ a,b ∈ Z+ a,bZ+,都有 f ( a b ) = f ( a ) × f ( b ) f(ab) = f(a) × f(b) f(ab)=f(a)×f(b),则称 f ( x ) f(x) f(x) 是一个完全积性函数

2.2 积性函数的性质
f ( x ) f(x) f(x) 是一个积性函数,且 x x x 的唯一分解式为 x = p 1 c 1 p 2 c 2 … p k c k x= p_1^{c_1} p_2^{c_2}…p_k^{c_k} x=p1c1p2c2pkck,则 f ( x ) = f(x) = f(x)= ∏ i = 1 k \prod_{i=1}^k i=1k f ( p i c i ) f(p_i^{c_i}) f(pici)

对于证明,显然每一项之间互质,于是按照积性函数的定义即可证明

注意这个性质是 f(x) 是积性函数的充要条件

三、简单的常见数论函数

在这里插入图片描述

3.1 欧拉函数

ϕ ( x ) ϕ(x) ϕ(x) 为在模 x 域下的简化剩余系大小,称为欧拉函数,显然欧拉函数是一个数论函数。并且欧拉函数是一个积性函数。

证明我不会

3.2 幺元函数

幺元函数 e ( x ) = [ x = 1 ] e(x) = [x = 1] e(x)=[x=1]我们约定中括号返回一个布尔量,中括号内表达式为真返回1,否则返回0

3.3 常函数 1

常函数 o n e ( x ) = 1 one(x) = 1 one(x)=1。不管自变量如何取值函数值恒为 1

3.4 标号函数

标号函数 I d ( x ) = x Id(x) = x Id(x)=x。即返回自变量本身

3.5 除数函数

σ ( k , x ) = ∑ d ∣ x d k σ(k,x) = ∑d∣xdk σ(k,x)=dxdk

当 k = 1 时,该函数表示 x 的因子之和

当 k = 0 时,该函数表示 x 的因子个数。

当 k 省略时默认为 1

容易证明上面五个函数都是积性函数除第一个和第五个外都是完全积性函数

四、莫比乌斯函数

暂时略过

五、狄利克雷卷积

5.1 狄利克雷卷积的定义

f f f g g g 都是数论函数,定义 f f f g g g 的狄利克雷卷积为 h,记为 h = f ∗ g h = f∗g h=fg

定义 h ( n ) = ∑ x ∗ y = n f ( x ) × g ( y ) h(n) = \sum_{x*y=n}f(x) × g(y) h(n)=xy=nf(x)×g(y)

显然狄利克雷卷积拥有交换律和结合律以及乘法对加法的分配律

这里介绍一下单位元
在这里插入图片描述

5.2 函数的积性

f f f g g g 都是积性函数,则 h h h 为积性函数

证明:
在这里插入图片描述

5.3 对因数求和函数的可卷性 (重点)

g ( n ) = ∑ d ∣ n f ( d ) , 则 g = f ∗ o n e g(n) = \sum_{d∣n} f(d),则 g = f∗one g(n)=dnf(d)g=fone。其中 o n e one one常函数 1

证明上,依照狄利克雷卷积的定义,等价于每一项都乘 1,对答案不产生影响。

这里要注意辨析一下与单位元卷积等于其本身



5.4 常见数论函数的狄利克雷卷积

5.4.1莫比乌斯函数

莫比乌斯函数的性质:

可以改写为

μ μ μ o n e = e one = e one=e
e 为幺元函数



5.4.2 除数函数与幂函数

在这里插入图片描述


5.4.3欧拉函数与恒等函数

在这里插入图片描述

5.5 关于分配率 结合律 交换律

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5.6 狄利克雷逆元

在这里插入图片描述
在这里插入图片描述
需要指出,积性函数必然存在逆元(因为 f ( 1 ) = 1 f(1) = 1 f(1)=1 ),且逆元仍是积性函数。

5.7 狄利克雷卷积求法

对于卷积的第n项可以直接枚举约数,在 n \sqrt n n 的时间内计算

但是对于狄利克雷卷积的 n n n

在这里插入图片描述

如果一项一项算的话就需要 n n n\sqrt n nn ,但实际上可以优化

x = d , y = i / d x=d,y=i/d x=d,y=i/d分别枚举 x , y x,y x,y对于 h [ x ∗ y ] + = f [ x ] ∗ g [ y ] h[x*y]+=f[x]*g[y] h[xy]+=f[x]g[y]即可。
时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn)

for(int i=1;i<=n;i++)
{
	for(int j=1;j<=n/i;j++)
	{
		h[i*j] = ( h[i*j] + g[j] * f[i] % qwq ) % qwq;
	}
}

对于卷k次的还可以用快速幂优化

for(int i=1;i<=n;i++) t[i]  = 1;
while( k )
	{
		if( k&1 )
		{
			tot++;
			if( tot==1 )
			{
				for(int i=1;i<=n;i++) g[i] = t[i];
			}
			else
			{
				for(int i=1;i<=n;i++) now[i] = 0;
				for(int i=1;i<=n;i++)
				{
					for(int j=1;j<=n/i;j++)
					{
						now[i*j] = ( now[i*j] + g[i] * t[j] % qwq ) % qwq;
					}
				}
				for(int i=1;i<=n;i++) g[i] = now[i];
			}
		}
		for(int i=1;i<=n;i++) now[i] = 0;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n/i;j++)
			{
				now[i*j] = ( now[i*j] + t[i] * t[j] % qwq ) % qwq;
			}
		}
		for(int i=1;i<=n;i++) t[i] = now[i];
		k>>=1;
	}




例题1:Longge 的问题

在这里插入图片描述


#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;

LL n,ans,sq;

LL phi(LL x)
{
	LL y = x;
	for(LL i=2;i<=sq;i++)
	{
		if( x%i==0 )
		{
			y = y / i * (i-1);
			while( x%i==0 ) x /= i;
		}
	}
	if( x>1 ) y = y / x * (x-1);
	return y;
}

void solve()
{
	scanf("%lld",&n);
	sq = sqrt(n);
	for(LL i=1;i<=sq;i++)
	{
		if( n%i==0 )
		{
			ans += i*phi( n/i );
			if( i*i<n )
			{
				ans += (n/i) * phi( i );
			}
		}
	}
	printf("%lld\n",ans);
}

int main()
{
	solve();
	return 0;
 } 




例题2:jzoj【NOI2017模拟3.27】B

鉴于大家是进不去jzoj的
在这里插入图片描述
Input
在这里插入图片描述
Output

在这里插入图片描述

Sample Input
2
6 2
2 3 3 3 3 3
23 3
2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
Sample Output
2 7 7 15 7 23
2 9 9 24 9 39 9 50 24 39 9 102 9 39 39 90 9 102 9 102 39 39 9
在这里插入图片描述

idea:
在这里插入图片描述

ACcode:

#include<bits/stdc++.h>
#define LL long long
#define N 101000
#define LL long long
#define qwq 1000000007
using namespace std;

LL T,n,f[N],g[N],now[N],t[N],k,tot = 0; 

void solve()
{
	scanf("%lld %lld",&n,&k);
	for(int i=1;i<=n;i++) scanf("%lld",&f[i]);
	for(int i=1;i<=n;i++) t[i] = g[i] = 1ll;
	tot = 0;
	while( k )
	{
		if( k&1 )
		{
			tot++;
			if( tot==1 )
			{
				for(int i=1;i<=n;i++) g[i] = t[i];
			}
			else
			{
				for(int i=1;i<=n;i++) now[i] = 0;
				for(int i=1;i<=n;i++)
				{
					for(int j=1;j<=n/i;j++)
					{
						now[i*j] = ( now[i*j] + g[i] * t[j] % qwq ) % qwq;
					}
				}
				for(int i=1;i<=n;i++) g[i] = now[i];
			}
		}
		for(int i=1;i<=n;i++) now[i] = 0;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n/i;j++)
			{
				now[i*j] = ( now[i*j] + t[i] * t[j] % qwq ) % qwq;
			}
		}
		for(int i=1;i<=n;i++) t[i] = now[i];
		k>>=1;
	}
	for(int i=1;i<=n;i++) now[i] = 0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n/i;j++)
		{
			now[i*j] = ( now[i*j] + g[j] * f[i] % qwq ) % qwq;
		}
	}
	for(int i=1;i<=n;i++) printf("%lld ",now[i]);
	printf("\n");
}

int main()
{
	freopen("b.in","r",stdin);
	freopen("b.out","w",stdout);
//	freopen("in.txt","r",stdin);
//	freopen("b.out","w",stdout);
	cin>>T;
	while( T-- )
	{
		solve();
	}
	return 0;
}









参考1
参考2
参考3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值