题目链接
http://www.spoj.com/problems/SWERC14C/
思路
FFT半裸题了。
如果一个多项式有
xi
x
i
项,另一个多项式有
xj
x
j
项,那么相乘后的多项式就一定有
xi+j
x
i
+
j
项。
那么如果读入一个数
i
i
,那么多项式项就赋值为
1
1
。
最后把多项式平方,得出多项式次数为哪些时,系数有值,说明这个次数能被凑出来。
代码
#include <cstdio>
#include <cmath>
#include <algorithm>
const int maxn=200000;
const double pi=acos(-1);
struct complex
{
double r,i;
complex(double r_=0,double i_=0)
{
r=r_;
i=i_;
}
complex operator +(const complex &other) const
{
return complex(r+other.r,i+other.i);
}
complex operator -(const complex &other) const
{
return complex(r-other.r,i-other.i);
}
complex operator *(const complex &other) const
{
return complex(r*other.r-i*other.i,r*other.i+i*other.r);
}
};
complex a[maxn<<2];
int rev[maxn<<2],n,m,ans;
int fft(complex* ar,int len,int op)
{
for(register int i=0; i<len; ++i)
{
if(rev[i]<i)
{
std::swap(ar[rev[i]],ar[i]);
}
}
for(register int i=2; i<=len; i<<=1)
{
complex wn(cos(2*pi/i),sin(2*pi*op/i));
for(register int j=0; j<len; j+=i)
{
complex w(1,0);
for(register int k=0; k<(i>>1); ++k)
{
complex x=ar[j+k],y=w*ar[j+k+(i>>1)];
ar[j+k]=x+y;
ar[j+k+(i>>1)]=x-y;
w=w*wn;
}
}
}
if(op==-1)
{
for(register int i=0; i<len; ++i)
{
ar[i].r/=len;
}
}
return 0;
}
inline int calc(int x)
{
int l=0;
m=1;
while(m<=x)
{
m<<=1;
++l;
}
for(register int i=0; i<m; ++i)
{
rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
}
return 0;
}
int main()
{
scanf("%d",&n);
for(register int i=1; i<=n; ++i)
{
int w;
scanf("%d",&w);
a[w].r=1;
}
a[0]=1;
calc(maxn<<1);
fft(a,m,1);
for(register int i=0; i<m; ++i)
{
a[i]=a[i]*a[i];
}
fft(a,m,-1);
scanf("%d",&n);
for(register int i=1; i<=n; ++i)
{
int w;
scanf("%d",&w);
if(a[w].r-0.5>0)
{
++ans;
}
}
printf("%d\n",ans);
return 0;
}