题目:
B Z O J 2194 BZOJ2194 BZOJ2194
求
c i = ∑ j = i n − 1 a j b j − i ( 0 ≤ i ≤ n − 1 ) c_i=\sum_{j=i}^{n-1}a_jb_{j-i}\quad (0\le i\le n-1) ci=j=i∑n−1ajbj−i(0≤i≤n−1)
思路:
把 a j a_j aj映射到 A n − 1 − j A_{n-1-j} An−1−j
c i = ∑ j = i n − 1 a j b j − i = ∑ j = i n − 1 A n − 1 − j b j − i 令 t = j − i = ∑ t = 0 n − 1 − i A n − 1 − i − t b t \begin{aligned} c_i&=\sum_{j=i}^{n-1}a_jb_{j-i}\\ &=\sum_{j=i}^{n-1}A_{n-1-j}b_{j-i}\quad 令t=j-i\\ &=\sum_{t=0}^{n-1-i}A_{n-1-i-t}b_t \end{aligned} ci=j=i∑n−1ajbj−i=j=i∑n−1An−1−jbj−i令t=j−i=t=0∑n−1−iAn−1−i−tbt
卷积 F F T FFT FFT,注意精度
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const double Pi=acos(-1.0);
const int N=300009;
struct com
{
double x,y;
com(double xx=0,double yy=0)
{
x=xx,y=yy;
}
}a[N],aa[N],b[N],c[N],cc[N];
com operator + (com a,com b)
{
return com(a.x+b.x,a.y+b.y);
}
com operator - (com a,com b)
{
return com(a.x-b.x,a.y-b.y);
}
com operator * (com a,com b)
{
return com(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
}
int n,m,bit=0,lim=1,r[N];
double sinn[N],coss[N];
void init()
{
while(lim<=2*n-1)
lim<<=1,bit++;
for(int i=1;i<lim;i<<=1)
sinn[i]=sin(Pi/i),coss[i]=cos(Pi/i);
for(int i=0;i<lim;i++)
r[i]=(r[i>>1]>>1)|((i&1)<<(bit-1));
}
void FFT(com *a,int type)
{
for(int i=0;i<lim;i++)
if(i<r[i])
swap(a[i],a[r[i]]);
for(int mid=1;mid<lim;mid<<=1)
{
com W(coss[mid],type*sinn[mid]);
for(int r=mid<<1,j=0;j<lim;j+=r)
{
com e(1,0);
for(int k=0;k<mid;k++,e=e*W)
{
com x=a[j+k],y=e*a[j+k+mid];
a[j+k]=x+y,a[j+k+mid]=x-y;
}
}
}
if(type==-1)
for(int i=0;i<lim;i++)
a[i].x/=lim;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lf%lf",&a[n-1-i].x,&b[i].x);
init();
FFT(a,1),FFT(b,1);
for(int i=0;i<lim;i++)
c[i]=a[i]*b[i];
FFT(c,-1);
for(int i=0;i<n;i++)
printf("%d\n",(int)(c[n-1-i].x+0.5));//注意精度
return 0;
}