[分治FFT] HDU5730 Shell Necklace
2018-02-09 23:25
295 查看
分治 FFTFFT,就是 CDQCDQ 分治加 FFTFFT。
用来解决这样的问题:已知 g(x)g(x),且
f(i)=∑i=0n−1f(i)g(n−i)f(i)=∑i=0n−1f(i)g(n−i)
求 f(x)f(x)。
就是直接 CDQCDQ 分治,算 [L,mid][L,mid] 对 [mid+1,R][mid+1,R] 的贡献时,只需对 f(x)[L,mid]f(x)[L,mid] 和 g(x)[1,R−L]g(x)[1,R−L] 乘一下。
复杂度 O(nlog2n)O(nlog2n)
这题显然就是
f(i)=∑j=1nf(i−j)ajf(i)=∑j=1nf(i−j)aj
裸题,貌似跑得挺快..
用来解决这样的问题:已知 g(x)g(x),且
f(i)=∑i=0n−1f(i)g(n−i)f(i)=∑i=0n−1f(i)g(n−i)
求 f(x)f(x)。
就是直接 CDQCDQ 分治,算 [L,mid][L,mid] 对 [mid+1,R][mid+1,R] 的贡献时,只需对 f(x)[L,mid]f(x)[L,mid] 和 g(x)[1,R−L]g(x)[1,R−L] 乘一下。
复杂度 O(nlog2n)O(nlog2n)
这题显然就是
f(i)=∑j=1nf(i−j)ajf(i)=∑j=1nf(i−j)aj
裸题,貌似跑得挺快..
#include<cstdio> #include<cstring> #include<cmath> #include<cctype> #include<algorithm> using namespace std; typedef long long LL; const int maxn=700005,MOD=313; const double PI=acos(-1); inline char gc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline int getint(){ char ch=gc(); int res=0,ff=1; while(!isdigit(ch)) ch=='-'?ff=-1:0, ch=gc(); while(isdigit(ch)) res=(res<<3)+(res<<1)+ch-'0', ch=gc(); return res*ff; } struct E{ double real,imag; E(double t1=0,double t2=0){ real=t1; imag=t2; } }; E operator + (const E &A,const E &B){ return E(A.real+B.real,A.imag+B.imag); } E operator - (const E &A,const E &B){ return E(A.real-B.real,A.imag-B.imag); } E operator * (const E &A,const E &B){ return E(A.real*B.real-A.imag*B.imag,A.real*B.imag+A.imag*B.real); } int rev[maxn]; void get_rev(int n){ int t=0; while((1<<t)<n) t++; rev[0]=0; for(int i=1;i<=n-1;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<t-1); } void FFT(E a[],int n,int k){ for(int i=0;i<=n-1;i++) if(i<rev[i]) swap(a[i],a[rev[i]]); for(int m=2;m<=n;m<<=1){ E wm(cos(2*PI/m),sin(2*PI/m)*k); for(int i=0;i<=n-1;i+=m){ E w(1,0),t0,t1; for(int j=0;j<=(m>>1)-1;j++,w=w*wm) t0=a[i+j], t1=w*a[i+j+(m>>1)], a[i+j]=t0+t1, a[i+j+(m>>1)]=t0-t1; } } if(k==-1) for(int i=0;i<=n-1;i++) a[i].real/=n, a[i].imag/=n; } int f[maxn],B[maxn]; E tmp1[maxn],tmp2[maxn]; void Divide(int L,int R){ if(L==R){ if(L==0) f[0]=1; return; } int mid=(L+R)>>1; Divide(L,mid); for(int i=L;i<=mid;i++) tmp1[i-L]=f[i]; for(int i=1;i<=R-L;i++) tmp2[i]=B[i]; int n=R-L+1,_n=1; while(_n<n) _n<<=1; n=_n; get_rev(n); FFT(tmp1,n,1); FFT(tmp2,n,1); for(int i=0;i<=n-1;i++) tmp1[i]=tmp1[i]*tmp2[i]; FFT(tmp1,n,-1); for(int i=mid+1;i<=R;i++) f[i]=(f[i]+(LL)(tmp1[i-L].real+0.1)%MOD)%MOD; for(int i=0;i<=n-1;i++) tmp1[i]=tmp2[i]=0; Divide(mid+1,R); } int n; int main(){ freopen("hdu5730.in","r",stdin); freopen("hdu5730.out","w",stdout); while(n=getint()){ for(int i=1;i<=n;i++) B[i]=getint()%MOD; for(int i=0;i<=n;i++) f[i]=0; Divide(0,n); printf("%d\n",f ); } return 0; }
相关文章推荐
- [DP] [1D1D优化] [FFT] [CDQ分治] [HDU5730] Shell Necklace
- hdu5730 Shell Necklace 【分治fft】
- 【HDU5730 2016 Multi-University Training Contest 1H】【FFT + cdq 分治】 Shell Necklace f[i]=∑f[i-j] x a[j]
- 【HDU5730】Shell Necklace(多项式运算,分治FFT)
- HDU5730 Shell Necklace(DP + CDQ分治 + FFT)
- HDU5730 FFT+CDQ分治
- 【ZOJ】3874 Permutation Graph 【FFT+CDQ分治】
- 【BZOJ5119】【CTT2017】生成树计数 DP 分治FFT 斯特林数
- 【XSY2666】排列问题 DP 容斥原理 分治FFT
- 【BZOJ 3451】Tyvj1953 Normal 思维题+期望概率+FFT+点分治
- HDU.5730.Shell Necklace(分治FFT)
- HDU 5730 2016多校Contest 1 G题【CDQ分治和FFT模板】
- codechef Prime Distance On Tree(树分治+fft)
- 解题报告:Prime Distance On Tree 点分治 + FFT
- bzoj 4836: [Lydsy2017年4月月赛]二元运算 -- 分治+FFT
- 【BZOJ4836】[Lydsy2017年4月月赛]二元运算 分治+FFT
- codechef Prime Distance On Tree(树分治+FFT)
- 【点分治】【FFT】Gym - 101234D - Forest Game
- 【XSY1529】小Q与进位制 分治 FFT
- [BZOJ4836]二元运算(分治FFT)