https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4898
简单FFT模板题
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int maxn = 100005; const double pi = acos(-1.0); const int low(int x){ return x&-x; }//树状数组的lowbit,可以计算二进制最右边的1 int n, m; class FFT { private: const static int maxn = 560000;//要注意长度是2^k方 class Plural { public: double x, y; Plural(double x = 0.0, double y = 0.0) :x(x), y(y){} Plural operator +(const Plural &a) { return Plural(x + a.x, y + a.y); } Plural operator -(const Plural &a) { return Plural(x - a.x, y - a.y); } Plural operator *(const Plural &a) { return Plural(x*a.x - y*a.y, x*a.y + y*a.x); } Plural operator /(const double &u) { return Plural(x / u, y / u); } };//定义复数的相关运算 Plural x[maxn], x1[maxn], x2[maxn]; Plural y[maxn], y1[maxn], y2[maxn]; int ans[maxn], X[maxn]; int n, len; public: int reverse(int x) { int ans = 0; for (int i = 1, j = n >> 1; j; i <<= 1, j >>= 1) if (x&i) ans |= j; return ans; }//数字倒序,FFT的初始步骤 Plural w(double x, double y) { return Plural(cos(2 * pi * x / y), -sin(2 * pi * x / y)); } bool setx() { if (scanf("%d", &len) == EOF) return false; for (n = 400000; n != low(n); n += low(n)); for (int i = 0; i < n; i++) { x[i] = Plural(0, 0); ans[i] = 0; } for (int i = n = 0; i < len; i++) { scanf("%d", &X[i]); x[X[i]].x += 1.0; n = max(n, X[i]); } for (n = n + n - 1; n != low(n); n += low(n)); return true; } void fft(Plural*x, Plural*y, int flag) { for (int i = 0; i < n; i++) y[i] = x[reverse(i)]; for (int i = 1; i < n; i <<= 1) { Plural uu = w(flag, i + i); for (int j = 0; j < n; j += i + i) { Plural u(1, 0); for (int k = j; k < j + i; k++) { Plural a = y[k]; //w(flag*(k - j), i + i) 可以去掉u和uu用这个代替,精度高些,代价是耗时多了 Plural b = u * y[k + i]; y[k] = a + b; y[k + i] = a - b; u = u*uu; } } } if (flag == -1) for (int i = 0; i < n; i++) y[i] = y[i] / n; }//1是FFT,-1是IFFT,答案数组是y数组 void solve() { fft(x, y, 1); for (int i = 0; i < n; i++) y[i] = y[i] * y[i]; fft(y, x, -1); for (int i = 0; i < n; i++) ans[i] = (int)(x[i].x + 0.5);//调整精度 for (int i = 0; i < len; i++) ans[X[i]]++; int u, v = 0; for (scanf("%d", &len); len; len--) { scanf("%d", &u); if (ans[u]) v++; } printf("%d", v); putchar(10); } }fft; int main() { while (fft.setx()) { fft.solve(); } return 0; }