BZOJ2194: 快速傅立叶之二
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2194
题目大意:请计算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n ,并且有 n < = 10 ^ 5。 a,b中的元素均为小于等于100的非负整数。
题解:这就是所谓的卷积,找个时间一定要好好看看,上FFT咯
代码:
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<cmath> 6 #define maxn 270005 7 #define pi acos(-1) 8 using namespace std; 9 int n,m; 10 int ans[maxn],rev[maxn]; 11 int l; 12 struct F{ 13 double rea,ima; 14 F operator +(const F &x){return (F){rea+x.rea,ima+x.ima};} 15 F operator -(const F &x){return (F){rea-x.rea,ima-x.ima};} 16 F operator *(const F &x){return (F){rea*x.rea-ima*x.ima,rea*x.ima+ima*x.rea};} 17 }a[maxn],b[maxn],c[maxn],w,wn,t1,t2; 18 int read() 19 { 20 int x=0; char ch; bool bo=0; 21 while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') bo=1; 22 while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9'); 23 if (bo) return -x; return x; 24 } 25 void fft(F *a,int type) 26 { 27 for (int i=0; i<n; i++) if (i<rev[i]) swap(a[i],a[rev[i]]); 28 for (int s=2; s<=n; s<<=1) 29 { 30 wn=(F){cos(type*2*pi/s),sin(type*2*pi/s)}; 31 for (int i=0; i<n; i+=s) 32 { 33 w=(F){1,0}; 34 for (int j=i; j<(i+(s>>1)); j++,w=w*wn) 35 { 36 t1=a[j],t2=a[j+(s>>1)]*w; 37 a[j]=t1+t2,a[j+(s>>1)]=t1-t2; 38 } 39 } 40 } 41 } 42 int re(int x) 43 { 44 int t=0; 45 for (int i=0; i<l; i++) t<<=1,t|=x&1,x>>=1; 46 return t; 47 } 48 void init() 49 { 50 m=read(); 51 for (n=1; n<2*m; n<<=1) l++; 52 for (int i=0; i<m; i++) 53 { 54 a[i].rea=read(),b[m-i-1].rea=read(); 55 } 56 for (int i=0; i<n; i++) rev[i]=re(i); 57 fft(a,1); fft(b,1); 58 for (int i=0; i<n; i++) c[i]=a[i]*b[i]; 59 fft(c,-1); 60 for (int i=0; i<n; i++) ans[i]=(int)(c[i].rea/n+0.5); 61 for (int i=m-1; i<2*m-1; i++) printf("%d\n",ans[i]); 62 63 } 64 int main() 65 { 66 init(); 67 }
我太蒟蒻了,所以神犇们留下意见让我跪膜