题目链接:bzoj2194
题目大意:
给出数组a,b,计算
c[k]=∑k≤i<na[i]×b[i−k]
题解:
FFT
按通常的卷积形式应该是
c[k]=∑ki=1a[i]×b[k−i]
要求和相等的
可是题目要的是
c[k]=∑ni=ka[i]×b[i−k]
【把n-1一下】
是差相等的
于是可以考虑把其中一个数组翻转一下。即令b[i]=b[n-i+1]这样子的翻转。
那么式子就变成了
c[k]=∑i=kna[i]×b[n−(i−k)]=∑i=kna[i]×b[n+k−i]
发现 i+(n+k−i)=n+k 符合通常的形式了。
令 d[n+k]=∑ni=ka[i]×b[n+k−i] ,这样就能直接上FFT了。
所以最后 c[0…n] 对应的就是 d[n+1…2n]
总结:
形如
c[k]=∑a[i]×b[i−k]
这样子的,可以把其中一个翻转过来做
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 100010
const double pi=acos(-1);
struct Complex
{
double x,y;
Complex(){x=y=0;}
Complex(double x,double y):x(x),y(y){}
friend inline Complex operator + (Complex x,Complex y){return Complex(x.x+y.x,x.y+y.y);}
friend inline Complex operator - (Complex x,Complex y){return Complex(x.x-y.x,x.y-y.y);}
friend inline Complex operator * (Complex x,Complex y){return Complex(x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x);}
}a[maxn*4],b[maxn*4];
void DFT(Complex *c,int ln,int t)
{
if (ln==1) return;
Complex A0[ln>>1],A1[ln>>1];
for (int i=0;i<=ln;i+=2) A0[i>>1]=c[i],A1[i>>1]=c[i+1];
DFT(A0,ln>>1,t);DFT(A1,ln>>1,t);
Complex wn(cos(2*pi/ln),t*sin(2*pi/ln)),w(1,0);
for (int i=0;i<(ln>>1);i++,w=w*wn)
{
c[i]=A0[i]+w*A1[i];
c[i+(ln>>1)]=A0[i]-w*A1[i];
}
}
int ans[maxn];
void FFT(int ln)
{
int fn=1;while (fn<=ln*2) fn<<=1;
DFT(a,fn,1);DFT(b,fn,1);
for (int i=0;i<=fn;i++) a[i]=a[i]*b[i];
DFT(a,fn,-1);
for (int i=0;i<=ln;i++) ans[i]=(int)(a[i+ln].x/fn+0.5);
}
int main()
{
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
int i,n;
scanf("%d",&n);n--;
for (i=0;i<=n;i++)
scanf("%lf%lf",&a[i].x,&b[i].x);
for (i=0;i<=n/2;i++) swap(b[i],b[n-i]);
FFT(n);
for (i=0;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}