1. 程式人生 > >BZOJ-4827-FFT

BZOJ-4827-FFT

先不考慮+c,那麼只需要把原式展開,將a陣列擴大一倍,求fft即可。

#include<bits/stdc++.h>
#define N 262144
#define pi acos(-1)
#define ll long long
using namespace std;
typedef complex<double> E;
int n,m,L;
int rev[N];
E f[N],_f[N],e[N];
void fft(E *a,int f)
{
	for(int i=0;i<n;i++)if(i>rev[i])swap(a[i],a[rev[i]]);
	for(int i=1;i<n;i<<=1)
	{
		E wn(cos(pi/i),f*sin(pi/i));
		for(int j=0;j<n;j+=(i<<1))
		{
			E w(1,0);
			for(int k=0;k<i;k++,w*=wn)
			{
				E x=a[j+k],y=w*a[j+k+i];
				a[j+k]=x+y;a[j+k+i]=x-y;
			}
		}
	}
	if(f==-1)for(int i=0;i<n;i++)a[i]/=n;
}
int t,a[N],b[N],c[N];
int pow(int x)
{
    return x*x;
}
int main()
{
    scanf("%d%d",&n,&t);
    int nn =n;
    for(int i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
        f[i]=a[i];
    }
    for(int i=n;i<2*n;i++)
        f[i]=f[i-n];
    int sum = 0, p =0;
    for(int i=0;i<n;i++)
    {
        scanf("%d",&b[i]);
        sum+=b[i];
        p += pow(b[i]);
        _f[n-1-i] = b[i];
    }
    m=2*n;
	for(n=1;n<=m;n<<=1)L++;
	for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
	fft(f,1);fft(_f,1);
	for(int i=0;i<n;i++) e[i] = f[i]*_f[i];
	fft(e,-1);
	
	//////////////////
	for(int i=0;i<2*nn;i++)
    {
        c[i] = (int)(e[i].real()+0.5);
        //printf("%d\n",c[i]);
    }
	int ans = 0x7fffffff;
	for(int k=-t;k<=t;k++)
    {
        int x = p;
        for(int i=0;i<nn;i++)
            x += pow(a[i]+k);
        for(int i=nn;i<2*nn;i++)
        {
            int xx = x - 2*(c[i]+sum*k);
            ans = min(ans,xx);
        }
    }
    printf("%d\n",ans);
    return 0;
}