题目链接:点击打开链接
题意:给定包含n个元素的集合A和包含m个元素的集合b,问集合B中有多少元素能通过从集合A中任选两个(可以重复)数字加和的得到。
思路:fft模版题
cpp:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <complex>
using namespace std;
const double PI =acos(-1);
const double EPS = 1e-5;
typedef complex<double> Complex;
void change(Complex y[],int len){
int i,j,k;
for(i=1,j=len/2;i<len-1;i++){
if(i<j)swap(y[i],y[j]);
k=len/2;
while(j>=k){
j-=k;
k/=2;
}
if(j<k) j+=k;
}
}
void fft(Complex y[],int len,int on){
change(y,len);
for(int h=2;h<=len;h<<=1){
Complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
for(int j=0;j<len;j+=h){
Complex w(1,0);
for(int k=j;k<j+h/2;k++){
Complex u=y[k];
Complex t=w*y[k+h/2];
y[k]=u+t;
y[k+h/2]=u-t;
w=w*wn;
}
}
}
if(on==-1){
for(int i=0;i<len;i++){
y[i]/=len;
}
}
}
const int maxn = 800010;
Complex x1[maxn];
int a[maxn/4];
long long num[maxn];
int main(){
int n,m;
// freopen("in.txt","r",stdin);
while(~scanf("%d",&n)){
memset(num,0,sizeof(num));
for(int i=0;i<n;i++){
scanf("%d",a+i);
num[a[i]]++;
}
num[0]++;
sort(a,a+n);
int len1=a[n-1]+1;
int len=1;
while(len<2*len1) len<<=1;
for(int i=0;i<len1;i++){
x1[i]=Complex(num[i],0);
}
for(int i=len1;i<len;i++){
x1[i]=Complex(0,0);
}
fft(x1,len,1);
for(int i=0;i<len;i++){
x1[i]=x1[i]*x1[i];
}
fft(x1,len,-1);
for(int i=0;i<len;i++){
num[i]=(long long)(x1[i].real()+EPS);
}
len=2*a[n-1];
int tp,ans=0;
scanf("%d",&m);
for(int i=0;i<m;i++){
scanf("%d",&tp);
if(num[tp]!=0){
ans++;
}
}
printf("%d\n",ans);
}
return 0;
}