FFT练习uoj#34;bzoj2179
2016-06-10 01:09
239 查看
FFT&FNT : http://blog.miskcoo.com/2015/04/polynomial-multiplication-and-fast-fourier-transform#Cooley-Tukey
FWT : http://picks.logdown.com/posts/179290-fast-walsh-hadamard-transform
中心思想:点值运算与插值运算
优化时间复杂度:选取n次单位复数根
难点:n次单位复数根的各种性质
重点:FFT的分治思想,DFT与逆DFT
不多说了,上面的链接讲的很详细。某ppt里的总结(如上)也是重点了。治愈至于模板,抄的上边的博主miskcoo的。嗯。很适合做模板的一种实现。有时间再学了FNT和FWT吧。
不压行才1kb啊。。虽然学弟吐槽我说我的代码就是压行。。
1、uoj#34 多项式乘法
不多说了直接干。
2、bzoj2179
大整数乘法。
FWT : http://picks.logdown.com/posts/179290-fast-walsh-hadamard-transform
中心思想:点值运算与插值运算
优化时间复杂度:选取n次单位复数根
难点:n次单位复数根的各种性质
重点:FFT的分治思想,DFT与逆DFT
不多说了,上面的链接讲的很详细。某ppt里的总结(如上)也是重点了。治愈至于模板,抄的上边的博主miskcoo的。嗯。很适合做模板的一种实现。有时间再学了FNT和FWT吧。
不压行才1kb啊。。虽然学弟吐槽我说我的代码就是压行。。
1、uoj#34 多项式乘法
不多说了直接干。
#include<cstdio> #include<complex> #include<cmath> #include<algorithm> #define N 262145 #define pi acos(-1.0) using namespace std; typedef complex<double> cd; cd f ,g ; cd eps ,c_eps ; int n,m; void init(){ for(int i=0;i<n;i++){ eps[i]=cd(cos(2.0*pi*i/n),sin(2.0*pi*i/n)); c_eps[i]=conj(eps[i]); } } void transform(int n,cd *x,cd *w){ for(int i=0,j=0;i<n;i++){ if(i>j) swap(x[i],x[j]); for(int l=n>>1;(j^=l)<l;l>>=1); } for(int i=2;i<=n;i<<=1){ int m=i>>1; for(int j=0;j<n;j+=i){ for(int k=0;k<m;k++){ cd z=x[j+m+k]*w[n/i*k]; x[j+m+k]=x[j+k]-z; x[j+k]=x[j+k]+z; } } } } int main(){ freopen("in.txt","r",stdin); scanf("%d%d",&n,&m); for(int i=0;i<=n;i++){double x;scanf("%lf",&x);f[i]=x;} for(int i=0;i<=m;i++){double x;scanf("%lf",&x);g[i]=x;} m=n+m;for(n=1;n<=m;n<<=1); init(); transform(n,f,eps);transform(n,g,eps); for(int i=0;i<n;i++) f[i]*=g[i]; transform(n,f,c_eps); for(int i=0;i<=m;i++) printf("%d ",(int)(f[i].real()/n+0.5)); return 0; }
2、bzoj2179
大整数乘法。
#include<cstdio> #include<complex> #include<cmath> #include<algorithm> #include<cstring> #define N 300000 #define pi acos(-1.0) using namespace std; typedef complex<double> cd; char s1 ,s2 ; cd f ,g ,eps ,c_eps ; int n,m,a ; void init(){ for(int i=0;i<n;i++){ eps[i]=cd(cos(2.0*pi*i/n),sin(2.0*pi*i/n)); c_eps[i]=conj(eps[i]); } } void transform(int n,cd *x,cd *w){ for(int i=0,j=0;i<n;i++){ if(i>j) swap(x[i],x[j]); for(int l=n>>1;(j^=l)<l;l>>=1); } for(int i=2;i<=n;i<<=1){ int m=i>>1; for(int j=0;j<n;j+=i) for(int k=0;k<m;k++){ cd z=x[j+k+m]*w[n/i*k]; x[j+k+m]=x[j+k]-z; x[j+k]=x[j+k]+z; } } } int main(){ freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); scanf("%s",s1);n=strlen(s1)-1; for(int i=0;s1[i];i++) f[i]=s1[n-i]-'0'; scanf("%s",s2);m=strlen(s2)-1; for(int i=0;s2[i];i++) g[i]=s2[m-i]-'0'; if(s1[0]=='0'||s2[0]=='0') {printf("%d",0);return 0;} m=m+n;for(n=1;n<=m;n<<=1); init(); transform(n,f,eps);transform(n,g,eps); for(int i=0;i<n;i++) f[i]*=g[i]; transform(n,f,c_eps); for(int i=0;i<=m;i++) a[i]=(int)(f[i].real()/n+0.5); for(int i=0;i<m;i++) a[i+1]+=a[i]/10,a[i]=a[i]%10; for(int i=m;i>=0;i--) printf("%d",a[i]); return 0; }