2194: 快速傅立叶之二
Time Limit: 10 Sec Memory Limit: 259 MB
Submit: 430 Solved: 240
[Submit][Status][Discuss]
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模板题。
FFT思想详见【BZOJ 2179】
FFT是计算下标为定值的两个多项式乘积的,而本题差是定值,我们只要把a[]数组逆序,就变成和为定值了!
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <complex>
#define N 500005
#define pi acos(-1)
#define LL long long
using namespace std;
int n;
complex<double> a[N],b[N],p[N];
void read(int &tmp)
{
tmp=0;
char ch=getchar();
int fu=1;
for (;ch<‘0‘||ch>‘9‘;ch=getchar())
if (ch==‘-‘) fu=-1;
for (;ch>=‘0‘&&ch<=‘9‘;ch=getchar())
tmp=tmp*10+ch-‘0‘;
tmp*=fu;
}
void FFT(complex<double> x[],int n,int p)
{
for (int i=0,t=0;i<n;i++)
{
if (i>t) swap(x[i],x[t]);
for (int j=n>>1;(t^=j)<j;j>>=1);
}
for (int m=2;m<=n;m<<=1)
{
complex<double> wn(cos(p*2*pi/m),sin(p*2*pi/m));
for (int i=0;i<n;i+=m)
{
complex<double> w(1,0),u;
int k=m>>1;
for (int j=0;j<k;j++,w*=wn)
{
u=x[i+j+k]*w;
x[i+j+k]=x[i+j]-u;
x[i+j]=x[i+j]+u;
}
}
}
}
int main()
{
scanf("%d",&n);
for (int i=0;i<n;i++)
{
int x;
read(x);
a[n-i-1]=x;
read(x);
b[i]=x;
}
int nn=n;
for (int j=n,i=1;(i>>1)<j;i<<=1)
n=i;
cout<<n<<endl;
FFT(a,n,1),FFT(b,n,1);
for (int i=0;i<n;i++)
p[i]=a[i]*b[i];
FFT(p,n,-1);
for (int i=nn-1;i>=0;i--)
printf("%lld\n",(LL)(p[i].real()/n+0.5));
return 0;
}
原文地址:http://blog.csdn.net/regina8023/article/details/44909229