do_while_true

一言(ヒトコト)

线性递推

bostan-mori

假设答案的 ogf 是 \(F(x)\),若 \(F(x)=\frac{P(x)}{Q(x)}\),对 \(Q(x)F(x)=P(x)\) 两边提取 \([x^n]\) 发现是个线性递推。

现在来直接计算 \([x^n]\frac{P(x)}{Q(x)}\),上下同乘 \(Q(-x)\) 得到 \(\frac{P(x)Q(-x)}{Q(x)Q(-x)}\),这时分母的奇数项都变成 0 了,那么算除法的时候分子的奇数项和偶数项之间就独立了。

假如 \(n\) 是奇数,那么分子只有奇数项有用,于是可以看成求 \([x^n]=\frac{xU(x^2)}{V(x^2)}=[x^{\frac{n-1}{2}}]\frac{U(x)}{V(x)}\),这里 \(U(x)\) 就是 \(P(x)Q(-x)\) 只把奇数项取出来然后从 \(0\) 往后排得到的多项式。偶数项的递归也是类似的。

只会递归 \(\log\) 次,那么这个算法的复杂度就是 \(\mathcal{O}(k\log k\log n)\) 的。

//[x^n]p(x)/q(x)
auto adjust=[&](Poly &f,int o){
	int i;
	for(i=o;i<(int)f.size();i+=2)
		f[i/2]=f[i];
	f.resize(i/2);
};
while(n){
	int o=(n&1);n>>=1;
	Poly rq=q;
	for(int i=1;i<(int)rq.size();i+=2)rq[i]=del(0,rq[i]);
	q=q*rq;
	adjust(q,0);
	p=p*rq;
	if(!o)adjust(p,0);
	else adjust(p,1);
}
if(p.size())cout<<1ll*p[0]*qpow(q[0],mod-2)%mod<<'\n';
else puts("0");
posted @ 2023-09-10 11:46  do_while_true  阅读(37)  评论(0编辑  收藏  举报