zoukankan      html  css  js  c++  java
  • 分治 FFT

    为啥要叫分治(fft)啊,又用不到(fft……)

    给定长度为(n-1)的数组(g[1],g[2],……,g[n-1]),求(f[1],f[2],……,f[n]),其中

    [f[i]=sumlimits_{j=1}^{i}f[j-i]g[j] ]

    边界为(f[0]=1),答案模(998244353)

    (2le n le 10^5,0le g[i]< 998244353)

    我们发现这其实是一个关于(f)数组的递推式子,但是肯定不能直接递推

    考虑每个对(f[i])有贡献的只有(f[1]sim f[i-1]),我们可以用(cdq)分治

    假设我们求出了(f[l->mid])的答案,想计算对(f[mid+1->r])的贡献

    那么对(tin [mid+1,r])的贡献为 (val_t=sumlimits_{i=l}^{mid}f[i]*g[t-i])

    是一个卷积形式,可以(ntt),得出(val_t)后直接加给(f[t])就好了

    其实点名是(cdq)分治思路就很清晰了吧,不过边界一如既往的恶心我

    #include<bits/stdc++.h>
    using namespace std;
    namespace red{
    #define int long long
    	inline int read()
    	{
    		int x=0;char ch,f=1;
    		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    		if(ch=='-') f=0,ch=getchar();
    		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    		return f?x:-x;
    	}
    	const int N=5e5+10,p=998244353,G=3,gi=332748118;
    	int n;
    	int g[N],f[N],pos[N];
    	int a[N],b[N];
    	inline int fast(int x,int k)
    	{
    		int ret=1;
    		while(k)
    		{
    			if(k&1) ret=ret*x%p;
    			x=x*x%p;
    			k>>=1;
    		}
    		return ret;
    	}
    	inline void ntt(int *a,int inv,int limit)
    	{
    		for(int i=0;i<limit;++i)
    			if(i<pos[i]) swap(a[i],a[pos[i]]);
    		for(int mid=1;mid<limit;mid<<=1)
    		{
    			int Wn=fast(inv?G:gi,(p-1)/(mid<<1));
    			for(int r=mid<<1,j=0;j<limit;j+=r)
    			{
    				int w=1;
    				for(int k=0;k<mid;++k,w=w*Wn%p)
    				{
    					int x=a[j+k],y=w*a[j+k+mid]%p;
    					a[j+k]=x+y;
    					if(a[j+k]>=p) a[j+k]-=p;
    					a[j+k+mid]=x-y;
    					if(a[j+k+mid]<0) a[j+k+mid]+=p;
    				}
    			}
    		}
    		if(inv) return;
    		inv=fast(limit,p-2);
    		for(int i=0;i<limit;++i) a[i]=a[i]*inv%p;
    	}
    	inline void cdq(int l,int r)
    	{
    		if(l==r) return;
    		int mid=(l+r)>>1;
    		cdq(l,mid);
    		int limit=1,len=0;
    		while(limit<=(mid-l+1)*2) limit<<=1,++len;
    		for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(len-1));
    		for(int i=0;i<limit;++i) a[i]=b[i]=0;
    		for(int i=l;i<=mid;++i) a[i-l]=f[i];
    		for(int i=1;i<=r-l+1;++i) b[i-1]=g[i];
    		ntt(a,1,limit);ntt(b,1,limit);
    		for(int i=0;i<limit;++i) a[i]=a[i]*b[i]%p;
    		ntt(a,0,limit);
    		for(int i=mid+1;i<=r;++i) (f[i]+=a[i-l-1])%=p;
    		cdq(mid+1,r);
    	}
    	inline void main()
    	{
    		n=read();
    		f[0]=1;
    		for(int i=1;i<n;++i) g[i]=read();
    		cdq(0,n-1);
    		for(int i=0;i<n;++i) printf("%lld ",f[i]);
    	}
    }
    signed main()
    {
    	red::main();
    	return 0;
    }
    
  • 相关阅读:
    AjaxPro对象参数传递
    SQLServer “无法对数据库'XX' 执行删除,因为它正用于复制”的解决方法
    sql server 查询某个表被哪些存储过程调用
    存储过程简单实例
    清理sqlserver 2012 日志文件
    从客户端(XXX)中检测到有潜在危险的Request.Form 值
    sqlserver无法在数据库上放置锁
    C#趋势图(highcharts插件)
    TFS 报错解决方案:tf400324
    checkbox勾选事件,JQ设置css,下拉框JQ选中
  • 原文地址:https://www.cnblogs.com/knife-rose/p/12056106.html
Copyright © 2011-2022 走看看