zoukankan      html  css  js  c++  java
  • 狄利克雷生成函数

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

    黎曼zeta函数(zeta(x)=sum_{nge 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_{nge 1}frac{f_n}{n^x}。 ]

    以下默认(nge 1,nin 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_pfrac{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_psum_{ige 0}frac{p^i}{p^{ix}}=prod_pfrac{1}{1-p^{-(x-1)}}=zeta(x-1))

    (f_n=phi(n))时:(F(x)=prod_p 1+frac{p-1}{p}sum_{ige 1}frac{1}{p^{i(x-1)}}=prod_pfrac{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(nln n)),用类似高维前缀和的方法好像可以做到(O(nln 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(nln n))

    求导、积分:

    [(frac{f_n}{n^x})'=-ln nfrac{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 eq ln 3),然而这里(c(2)=c(3)=1)

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

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

    所以并不需要满足(ln 2 eq 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("****
    ");
    			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("
    ");
    //	getpow(g,f,k);
    //	for (int i=1;i<=n;++i)
    //		printf("%lld ",g[i]);
    //	printf("
    ");
    	return 0;
    }
    
  • 相关阅读:
    fedora上部署ASP.NET——(卡带式电脑跑.NET WEB服务器)
    SQL Server 请求失败或服务未及时响应。有关详细信息,请参见事件日志或其它适合的错误日志
    8086CPU的出栈(pop)和入栈(push) 都是以字为单位进行的
    FTP 服务搭建后不能访问问题解决
    指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配
    Linux 安装MongoDB 并设置防火墙,使用远程客户端访问
    svn Please execute the 'Cleanup' command. 问题解决
    .net 操作MongoDB 基础
    oracle 使用绑定变量极大的提升性能
    尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。
  • 原文地址:https://www.cnblogs.com/jz-597/p/14403977.html
Copyright © 2011-2022 走看看