ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

狄利克雷生成函数

2021-02-15 17:03:28  阅读:228  来源: 互联网

标签:frac 函数 狄利克 ln sum 生成 int zeta prod


注意本文中用的字母可能和其他博客中有区别。

黎曼zeta函数\(\zeta(x)=\sum_{n\ge 1} \frac{1}{n^x}\)。

手写时本人喜欢写成\(z\)(因为\(\zeta\)太难写),但是在博客中还是正式点吧。


参考资料:

https://zhuanlan.zhihu.com/p/50817119

https://blog.csdn.net/luositing/article/details/109204796


形式

狄利克雷生成函数(DGF)形式:

\[F(x)=\sum_{n\ge 1}\frac{f_n}{n^x}。 \]

以下默认\(n\ge 1,n\in Z\)。

不难发现在这个形式下,如果有\(H(x)=F(x)G(x)\),那么有\(h_n=\sum_{d|n} f_dg_{\frac{n}{d}}\),也就是说\(h\)是\(f,g\)的狄利克雷卷积。


常用数论函数的DGF

当\(\forall n,f_n=1\)时,\(F(x)=\zeta(x)\)。

根据数论函数的基本性质,可以得到

\[\zeta(x)=\prod_p1+p^{-x}+p^{-2x}+\dots=\prod_p\frac{1}{1-p^{-x}} \]

当\(f_n=\mu(n)\)时:根据\(\mu\)的定义可得\(F(x)=\prod_p1-p^{-x}\)。于是有\(F(x)=\frac{1}{\zeta(x)}\)。

当\(f_n=n\)时:\(F(x)=\prod_p\sum_{i\ge 0}\frac{p^i}{p^{ix}}=\prod_p\frac{1}{1-p^{-(x-1)}}=\zeta(x-1)\)。

当\(f_n=\phi(n)\)时:\(F(x)=\prod_p 1+\frac{p-1}{p}\sum_{i\ge 1}\frac{1}{p^{i(x-1)}}=\prod_p\frac{1-p^{-x}}{1-p^{-(x-1)}}=\frac{\zeta(x-1)}{\zeta(x)}\)。

当\(f_n=\sigma_0(n)\)时:\(F(x)=\zeta^2(x)\)。

当\(f_n=\sigma_1(n)\)时:\(F(x)=\zeta(x)\zeta(x-1)\)。

通过这些东西,可以很直观地发现一些性质,什么\(I*\mu=e\),\(I*\phi=id\),\(\sigma_0*\phi=\sigma_1\)之类的。


DGF的运算

加减不说,乘法朴素\(O(n\ln n)\),用类似高维前缀和的方法好像可以做到\(O(n\ln \ln n)\)。

除法:假如有\(H(x)=F(x)G(x)\),已知\(H(x),F(x)\),则有\(h_n=\sum_{d|n,d>1}f_dg_{\frac{n}{d}}+f_1g_n\),移项得到\(g_n\)。时间\(O(n\ln n)\)。

求导、积分:

\[(\frac{f_n}{n^x})'=-\ln n\frac{f_n}{n^x}\\ \int \frac{f_n}{n^x}dx=-\frac{1}{\ln n}\frac{f_n}{n^x} \]

\(\ln n\)似乎不好处理。注意到求导和积分往往是成对存在的,不妨找个\(\ln n\)的替代品。定义\(c(n)\)表示\(n\)的可重质因子个数,用它来替代。这个函数也满足\(\ln\)的部分性质:\(c(1)=0,c(ab)=c(a)+c(b)\)。

它好像没有复刻\(ln\)的全部性质,为什么是对的?以下谈谈本人的感性理解:

当然如果有高深的高等数学知识可以略过

我认为这个疑问都来自于不同质数之间的关系,比如\(\ln 2\neq \ln 3\),然而这里\(c(2)=c(3)=1\)。

但是其实可以把每个质数看成一个维度,其指数为在这一维上的坐标,于是每个数都相当于无限维空间中的一个点。

我们可以把所有数重标号一下,把质因子\(2\)全部换成\(3\),把质因子\(3\)全部换成\(2\),相当于两个维度换一下。如果\(\ln 2\neq\ln 3\)对求导积分之后的结果有影响,不符合对称性,矛盾。

所以并不需要满足\(\ln 2\neq \ln 3\)。

于是变成这样:

\[(\frac{f_n}{n^x})'=c(n)\frac{f_n}{n^x}\\ \int \frac{f_n}{n^x}dx=\frac{1}{c(n)}\frac{f_n}{n^x} \]

求\(\ln\):\(\ln F(x)=\int \frac{F'(x)}{F(x)}dx\)。

求\(exp\):设\(G(x)=e^{F(x)}\),则\(G'(x)=F'(x)G(x)\)。把式子拆开,用类似除法的方式做就行了。


例题

PE639(题解):https://www.cnblogs.com/jz-597/p/14402383.html

LOJ6713. 「EC Final 2019」狄利克雷 k 次根 加强版。下面贴代码:

using namespace std;
#include <bits/stdc++.h>
#define N 1000005
#define mo 998244353
#define ll long long
ll qpow(ll x,ll y=mo-2){
	ll r=1;
	for (;y;y>>=1,x=x*x%mo)
		if (y&1)
			r=r*x%mo;
	return r;
}
int n,k;
ll g[N],f[N];
int p[N],np;
bool inp[N];
int c[N],inv[N];
void init(){
	c[1]=0;
	for (int i=2;i<=n;++i){
		if (!inp[i])
			p[++np]=i,c[i]=1;
		for (int j=1;j<=np && i*p[j]<=n;++j){
			inp[i*p[j]]=1;
			c[i*p[j]]=c[i]+1;
			if (i%p[j]==0)
				break;
		}
	}
	inv[1]=1;
	for (int i=2;i<=n;++i)
		inv[i]=(ll)(mo-mo/i)*inv[mo%i]%mo;
}
void check(ll h[],ll f[],ll g[]){
	static ll t[N];
	for (int i=1;i<=n;++i)
		for (int j=1;i*j<=n;++j)
			(t[i*j]+=f[i]*g[j])%=mo;
	for (int i=1;i<=n;++i)
		if (t[i]!=h[i]){
			printf("****\n");
			exit(0);
		}
}
void getdiv(ll h[],ll f[],ll g[]){
	static ll d[N];
	memset(d,0,sizeof(ll)*(n+1));
	ll t=qpow(g[1]);
	for (int i=1;i<=n;++i){
		d[i]=(d[i]+mo+f[i])*t%mo;
		for (int j=2;i*j<=n;++j)
			(d[i*j]-=d[i]*g[j])%=mo;
	}
	memcpy(h,d,sizeof(ll)*(n+1));
	check(f,g,h);
}
void getln(ll f[],ll g[]){
	static ll g_[N],_f[N];
	for (int i=1;i<=n;++i)
		g_[i]=g[i]*c[i]%mo;
	getdiv(_f,g_,g);
	f[1]=0;
	for (int i=2;i<=n;++i)
		f[i]=_f[i]*inv[c[i]]%mo;
}
void getexp(ll g[],ll f[]){
	static ll d[N];
	memset(d,0,sizeof(ll)*(n+1));
	assert(f[1]==0);
	d[1]=1;
	for (int j=2;j<=n;++j)
		(d[j]+=c[j]*f[j])%=mo;
	for (int i=2;i<=n;++i){
		d[i]=d[i]*inv[c[i]]%mo;
		for (int j=2;i*j<=n;++j)
			(d[i*j]+=c[j]*f[j]%mo*d[i])%=mo;
	}
	memcpy(g,d,sizeof(ll)*(n+1));
}
void getpow(ll h[],ll g[],ll t){
	static ll d[N];
	getln(d,g);
	for (int i=1;i<=n;++i)
		d[i]=d[i]*t%mo;
	getexp(h,d);
}
int main(){
//	freopen("in.txt","r",stdin);
	scanf("%d%d",&n,&k);
	init();
	for (int i=1;i<=n;++i)
		scanf("%lld",&g[i]);
	getpow(f,g,qpow(k));
	for (int i=1;i<=n;++i)
		printf("%lld ",f[i]);
//	printf("\n");
//	getpow(g,f,k);
//	for (int i=1;i<=n;++i)
//		printf("%lld ",g[i]);
//	printf("\n");
	return 0;
}

标签:frac,函数,狄利克,ln,sum,生成,int,zeta,prod
来源: https://www.cnblogs.com/jz-597/p/14403977.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有