hihocoder-1388-高精度fft

来源:互联网 发布:php程序员面试题 编辑:程序博客网 时间:2024/05/22 08:17

感谢师兄的blog终于让我初略得明白卷积,dft及fft可以用来干什么。。

附上链接:http://blog.csdn.net/viphong/article/details/52665620

其实就是求一个循环卷积,然后把他转化成求对应相关系数的最大值,因为卡精度,所以我们只能求得最大时的k值;

AC代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<cmath>using namespace std;typedef long long ll;const double PI = acos(-1.0);struct complex{    double r,i;    complex(double _r = 0,double _i = 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 maxn=240010;complex x1[maxn],x2[maxn];ll a[maxn/4],b[maxn/4],sum[maxn];void init(){memset(a,0,sizeof(a));memset(b,0,sizeof(b));memset(x1,0,sizeof(x1));memset(x2,0,sizeof(x2));}int main(){    int cas;    int n;    scanf("%d",&cas);    while(cas--)    {        init();        scanf("%d",&n);     ll s1=0,s2=0;for(int i=0;i<n;i++)scanf("%lld",&a[i]),s1+=a[i]*a[i];for(int i=0;i<n;i++)scanf("%lld",&b[i]),s2+=b[i]*b[i];int len=1;while(len<2*n)len<<=1;for(int i=0;i<n;i++)x1[i]=complex(a[i],0);for(int i=0;i<n;i++)x2[i]=complex(b[n-1-i],0);fft(x1,len,1);fft(x2,len,1);for(int i=0;i<len;i++)x1[i]=x1[i]*x2[i];fft(x1,len,-1);for(int i=0;i<len;i++)sum[i]=(ll)(x1[i].r+0.5);ll ans=sum[n-1]+sum[2*n-1];int tar=0;for(int i=0;i<n-1;i++){if(ans<sum[i]+sum[n+i]){ans=sum[i]+sum[n+i];tar=n-i-1;}}   ans=0;for(int i=0;i<n;i++)ans+=a[i]*b[(i+tar)%n];printf("%lld\n",s1+s2-ans*2);    }    return 0;} 


原创粉丝点击