Description
请计算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n ,并且有 n < = 10 ^ 5。 a,b中的元素均为小于等于100的非负整数。
Input
第一行一个整数N,接下来N行,第i+2..i+N-1行,每行两个数,依次表示a[i],b[i] (0 < = i < N)。
Output
输出N行,每行一个整数,第i行输出C[i-1]。
Sample Input
5
3 1
2 4
1 1
2 4
1 4
Sample Output
24
12
10
6
1
分析:萌新又来刷水题啦。fft的板子题。我居然把单位复根的cos和sin打反了,怕不是数学白学了。
代码:
/**************************************************************
Problem: 2194
User: beginend
Language: C++
Result: Accepted
Time:2848 ms
Memory:15352 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cmath>
const int maxn=4e5+7;
const double pi=acos(-1);
struct rec{
double x,y;
};
rec operator +(rec x,rec y)
{
return (rec){x.x+y.x,x.y+y.y};
}
rec operator -(rec x,rec y)
{
return (rec){x.x-y.x,x.y-y.y};
}
rec operator *(rec x,rec y)
{
return (rec){x.x*y.x-x.y*y.y,x.y*y.x+x.x*y.y};
}
using namespace std;
rec a[maxn],b[maxn];
int r[maxn];
int n,l,lg;
void fft(rec *a,int f)
{
for (int i=0;i<l;i++)
{
if (r[i]>i) swap(a[i],a[r[i]]);
}
for (int i=2;i<=l;i*=2)
{
rec wn=(rec){cos(2*pi/i),f*sin(2*pi/i)};
for (int j=0;j<l;j+=i)
{
rec w=(rec){1,0};
for (int k=0;k<i/2;k++)
{
rec u=a[j+k],v=w*a[j+k+i/2];
a[j+k]=u+v;
a[j+k+i/2]=u-v;
w=w*wn;
}
}
}
}
int main()
{
scanf("%d",&n);
for (int i=0;i<n;i++)
{
scanf("%lf%lf",&a[n-i-1].x,&b[i].x);
}
l=1;lg=0;
while (l<=(n*2)) l*=2,lg++;
for (int i=0;i<l;i++) r[i]=((r[i>>1]>>1)|((i&1)<<(lg-1)));
fft(a,1);
fft(b,1);
for (int i=0;i<l;i++)
{
a[i]=a[i]*b[i];
}
fft(a,-1);
for (int i=n-1;i>=0;i--) printf("%.0lf\n",a[i].x/l+0.01);
}