题目大意:
就是现在给出N个数, 然后给出M个数询问这M书中有多少个可以是由这N个数中两个相加(同一个数可选两次)组成或者等于这N个数中的某一个
大致思路:
就是构造多项式相乘就可以了, FFT的最简单的应用了, 将N个数a1, a2,...an对应成多项式, 用x^k的系数是1表示N个数中有值为k的, 否则系数用0表示
然后求这个多项式的平方就可以了
代码如下:
Result : Accepted Memory : 0 KB Time : 785 ms
/* * Author: Gatevin * Created Time: 2015/7/17 14:08:34 * File Name: UVALive6886.cpp */ #include<iostream> #include<sstream> #include<fstream> #include<vector> #include<list> #include<deque> #include<queue> #include<stack> #include<map> #include<set> #include<bitset> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<cctype> #include<cmath> #include<ctime> #include<iomanip> using namespace std; const double eps(1e-8); typedef long long lint; const double PI = acos(-1.0); struct Complex { double real, image; Complex(double _real, double _image) { real = _real; image = _image; } Complex(){} }; Complex operator + (const Complex &c1, const Complex &c2) { return Complex(c1.real + c2.real, c1.image + c2.image); } Complex operator - (const Complex &c1, const Complex &c2) { return Complex(c1.real - c2.real, c1.image - c2.image); } Complex operator * (const Complex &c1, const Complex &c2) { return Complex(c1.real*c2.real - c1.image*c2.image, c1.real*c2.image + c1.image*c2.real); } int rev(int id, int len) { int ret = 0; for(int i = 0; (1 << i) < len; i++) { ret <<= 1; if(id & (1 << i)) ret |= 1; } return ret; } Complex A[1 << 19]; void FFT(Complex *a, int len, int DFT) { for(int i = 0; i < len; i++) A[rev(i, len)] = a[i]; for(int s = 1; (1 << s) <= len; s++) { int m = (1 << s); Complex wm = Complex(cos(DFT*2*PI/m), sin(DFT*2*PI/m)); for(int k = 0; k < len; k += m) { Complex w = Complex(1, 0); for(int j = 0; j < (m >> 1); j++) { Complex t = w*A[k + j + (m >> 1)]; Complex u = A[k + j]; A[k + j] = u + t; A[k + j + (m >> 1)] = u - t; w = w*wm; } } } if(DFT == -1) for(int i = 0; i < len; i++) A[i].real /= len, A[i].image /= len; for(int i = 0; i < len; i++) a[i] = A[i]; return; } Complex dis[1 << 19]; bool ok[200010]; int main() { int n, m; while(~scanf("%d", &n)) { memset(ok, 0, sizeof(ok)); int maxDis = 0; int tmp; for(int i = 0; i < n; i++) scanf("%d", &tmp), ok[tmp] = 1, maxDis = max(maxDis, tmp); for(int i = 0; i <= maxDis; i++) if(ok[i]) dis[i] = Complex(1, 0); else dis[i] = Complex(0, 0); int len = 1; while(len <= maxDis) len <<= 1; len <<= 1; for(int i = maxDis + 1; i < len; i++) dis[i] = Complex(0, 0); FFT(dis, len, 1); for(int i = 0; i < len; i++) dis[i] = dis[i]*dis[i]; FFT(dis, len, -1); int ans = 0; scanf("%d", &m); for(int i = 0; i < m; i++) { scanf("%d", &tmp); if(tmp <= maxDis*2 && (dis[tmp].real > 0.5 || ok[tmp])) ans++; } printf("%d\n", ans); } return 0; }