另类分治fft

89 篇文章 0 订阅
72 篇文章 0 订阅

遇到一道题求f(x)=sigma f(i)×f(x-i)这样的,做法是这样的:(下面F与G都与f有关),不严谨的一个证明:考虑左端点为1,例如[1...8]区间,那么求完[1...4],此时考察的是两项都是左区间相乘对右边点的贡献,比如5,能发现f[1] * f[4] 以及f[4] * f[1]都有了,因此只要像正常分治fft做即可;左端点不是1时,比如[5..8] 中[5,6]对[7,8]贡献,可以发现此时考察的是一项为左区间另一项为之前已经算出来的值相乘对右端点贡献(因为容易证明递归到的区间[l..r]当l>1时一定有l*2 > r),那么此时像正常分治做就只计算了一次f[7]+=f[2] * f[5],需要额外计算一个f[7] += f[5] * f[2]

if(l==r)
	{
		if(l==1)f[l]=1;
		else Mul(f[l],jc[l-2]);
		return;
	}
	int mid=(l+r)>>1;
	sol(l,mid);
	pre_ntt(r-l+2);
	for(int i=0;i<len;i++)A[i]=B[i]=0;
	for(int i=l;i<=mid;i++)A[i-l]=F(i);//1LL*(jc[i-1]-f[i]+mod)%mod*ijc[i-1]%mod;
	for(int i=1;i<=r-l;i++)B[i]=G(i);
	ntt(A,0),ntt(B,0);
	for(int i=0;i<len;i++)A[i]=1LL*A[i]*B[i]%mod;
	ntt(A,1);
	for(int i=mid+1;i<=r;i++)Ad(f[i],A[i-l]);
	if(l>1)
	{
		for(int i=0;i<len;i++)A[i]=B[i]=0;
		for(int i=l;i<=mid;i++)A[i-l]=G(i);//1LL*(jc[i-1]-f[i]+mod)%mod*ijc[i-1]%mod;
		for(int i=1;i<=r-l;i++)B[i]=F(i);
		ntt(A,0),ntt(B,0);
		for(int i=0;i<len;i++)A[i]=1LL*A[i]*B[i]%mod;
		ntt(A,1);
		for(int i=mid+1;i<=r;i++)Ad(f[i],A[i-l]);
	}
	sol(mid+1,r);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值