题意:一个有N个元素的A集合,然后在给你一个由M个数的B集合,问你,从A集合中取一次 或 两次得到的和 能得到的集合B中的数的个数
如A:1,3,5
B:2,4,5,7,8,9
那么有B中有2(1+1),4(1+3),5(5),8(1+3+5) ,一共有4个数可以得到
FFT模板题
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <vector> using namespace std; const double PI = acos(-1.0); struct complex { double r,i; complex(double _r = 0.0,double _i = 0.0) { r = _r; i = _i; } complex operator +(const complex &b) { return complex(r+b.r,i+b.i); } complex operator -(const complex &b) { return complex(r-b.r,i-b.i); } complex operator *(const complex &b) { return complex(r*b.r-i*b.i,r*b.i+i*b.r); } }; 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].r /= len; } const int N = 300005; complex x[N<<1]; int main(){ int n,m,u; while(~scanf("%d",&n)){ memset(x,0,sizeof(x)); int mx = 0; x[0].r = 1; for(int i = 0; i < n; i++){ scanf("%d",&u); x[u].r++; mx = max(u,mx); } int len = 1; while(len < 2*mx)len <<= 1; fft(x,len,1); for(int i = 0; i < len; i++){ x[i] = x[i] * x[i]; } fft(x,len,-1); int ans = 0; scanf("%d",&m); for(int i = 0; i < m; i++){ scanf("%d",&u); if((int)(x[u].r+0.5))ans++; } printf("%d\n",ans); } return 0; }