一种快速的常系数齐次线性递推算法

论文参考
https://arxiv.org/pdf/2008.08822.pdf

首先常系数齐次线性递推问题可以转化为这样一个问题
给定多项式\(p(x)\)和多项式\(q(x)\),求\(\frac{p(x)}{q(x)}\)\(n\)次项系数,\(n\)可能很大。
具体转化的话
大概是设递推式为\(f_n=\sum_{i=1}^{len} f_{n-i}*g_i\)
我们要做的就是求出这个递推式\(f_n\)的生成函数。
可以证明其可以表示为\(\frac{p(x)}{q(x)}\)的形式
其中\(q(x)=1-g(x)\)\(p(x)=f(x)*(1-g(x)) (mod \ x^{len})\)
证明不是很会。
我们考虑怎么求解\(\frac{p(x)}{q(x)}\)的第\(n\)

\[\frac{f(x)}{g(x)}=\frac{p(x)*q(-x)}{q(x)q(-x)} \]

\(v(x)=q(x)q(-x)\)
有这样一个性质,\(v(x)=v(-x)\),所以$v(x)只有偶数次项有值
所以

\[\frac{p(x)}{q(x)}=\frac{L(x^2)}{U(x^2)}+x*\frac{R(x^2)}{U(x^2)} \]

按照这个式子以及\(n\)的奇偶性向下递归即可。

int t[N],p[N],q[N],dp[N],dq[N],ddp[N],ddq[N]; 
int coefficient(int n,int len)
{
	int v=inv(2),wn=ksm(h,(mo-1)/(2*len)),wm=inv(wn); 
	
	for(int i=0;i<len;i++)dp[i]=p[i],dq[i]=q[i];
	ntt(dp,len,+1);ntt(dq,len,+1);
	while(n) 
	{
		//ddp ddq
		for(int i=0;i<len;i++)ddp[2*i]=dp[i],ddq[2*i]=dq[i];
		for(int i=0,w=1;i<len;i++,w=1ll*w*wn%mo)p[i]=1ll*p[i]*w%mo,q[i]=1ll*q[i]*w%mo;
		ntt(p,len,+1);ntt(q,len,+1);
		for(int i=0;i<len;i++)ddp[2*i+1]=p[i],ddq[2*i+1]=q[i];
		//p dp
		for(int i=0;i<2*len;i++)t[i]=1ll*ddp[i]*ddq[i^len]%mo;
		if(n&1)for(int i=0,w=1;i<2*len;i++,w=1ll*w*wm%mo)t[i]=1ll*t[i]*w%mo;
		for(int i=0;i<len;i++)t[i]=1ll*v*inc(t[i],t[i+len])%mo,dp[i]=t[i];
		ntt(t,len,-1);for(int i=0;i<len;i++)p[i]=t[i];	
		//q dq
		for(int i=0;i<2*len;i++)t[i]=1ll*ddq[i]*ddq[i^len]%mo;
		for(int i=0;i<len;i++)t[i]=1ll*v*inc(t[i],t[i+len])%mo,dq[i]=t[i];
		ntt(t,len,-1);for(int i=0;i<len;i++)q[i]=t[i];
		
		n>>=1; 
	}
	return 1ll*p[0]*inv(q[0])%mo;
}
int recurrence(int *f,int *g,int n,int k)
{
	int len=1;
	while(len<(n+1))len<<=1;
	for(int i=0;i<len;i++)p[i]=q[i]=0; 
	q[0]=1;for(int i=1;i<=n;i++)q[i]=dec(0,g[i]);
	
	for(int i=0;i<n;i++)a[i]=f[i];
	for(int i=0;i<=n;i++)b[i]=q[i];
	poly_mul(len,len); 
	for(int i=0;i<n;i++)p[i]=a[i];
	
	return coefficient(k,len);
}

posted @ 2021-12-09 06:54  Creed-qwq  阅读(80)  评论(0编辑  收藏  举报