UVALive 6886 Golf Bot

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;
}


你可能感兴趣的:(uvalive)