FFT学习

看了一天的多项式的内容,看博客的时候好像还是那么回事,一看题,哇塞,发现我其实连卷积是啥都没看懂。

qtdydb,背板子。 不知道卷积是啥就很伤了。

P3803 【模板】多项式乘法(FFT)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

typedef long long LL;

inline int read()
{
    char c=getchar();int num=0,f=1;
    for(;!isdigit(c);c=getchar())
        f=c=='-'?-1:f;
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num*f;
}

const int N=4e6+5;
const double pi=acos(-1);

int n,m,bit,len=1;
int rev[N];

struct Complex
{
    double x,y;
    Complex(double xx=0,double yy=0){x=xx,y=yy;}
    Complex operator + (const Complex &A){return Complex(x+A.x,y+A.y);}
    Complex operator - (const Complex &A){return Complex(x-A.x,y-A.y);}
    Complex operator * (const Complex &A){return Complex(x*A.x-y*A.y,x*A.y+y*A.x);}
}a[N],b[N];

void fft(Complex *A,int dft)
{
    for(int i=0;i<len;++i)
        if(i<rev[i]) swap(A[i],A[rev[i]]);
    for(int step=1;step<len;step<<=1)
    {
        Complex wn(cos(pi/step),dft*sin(pi/step));
        for(int j=0;j<len;j+=(step<<1))
        {
            Complex wnk(1,0);
            for(int k=j;k<step+j;++k)
            {
                Complex x=A[k],y=wnk*A[k+step];
                A[k]=x+y,A[k+step]=x-y;
                wnk=wnk*wn;
            }
        }
    }
    if(dft==1) return;
    for(int i=0;i<=n+m;++i) A[i].x/=len;
}

int main()
{
    n=read(),m=read();
    for(int i=0;i<=n;++i) a[i].x=read();
    for(int i=0;i<=m;++i) b[i].x=read();
    while(len<=n+m) len<<=1,++bit;
    for(int i=0;i<len;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
    fft(a,1),fft(b,1);
    for(int i=0;i<=len;++i) a[i]=a[i]*b[i];
    fft(a,-1);
    for(int i=0;i<=n+m;++i)
        cout<<(int)(a[i].x+0.5)<<' ';
    return 0;
}
View Code

P3338 [ZJOI2014]力

不会,抄的

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

typedef long long LL;

inline int read()
{
    char c=getchar();int num=0,f=1;
    for(;!isdigit(c);c=getchar())
        f=c=='-'?-1:f;
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num*f;
}

const int N=4e5+5;
const double pi=acos(-1);

int n,m,bit,len=1,rev[N];

struct Complex
{
    double x,y;
    Complex(double xx=0,double yy=0){x=xx,y=yy;}
    Complex operator + (const Complex &A){return Complex(x+A.x,y+A.y);}
    Complex operator - (const Complex &A){return Complex(x-A.x,y-A.y);}
    Complex operator * (const Complex &A){return Complex(x*A.x-y*A.y,x*A.y+y*A.x);}
}a[N],b[N],c[N];

void fft(Complex *A,int dft)
{
    for(int i=0;i<len;++i)
        if(i<rev[i]) swap(A[i],A[rev[i]]);
    for(int i=1;i<len;i<<=1)
    {
        Complex wn(cos(pi/i),dft*sin(pi/i));
        for(int j=0,t=i*2;j<len;j+=t)
        {
            Complex wnk(1,0);
            for(int k=j;k<i+j;++k)
            {
                Complex x=A[k],y=wnk*A[k+i];
                A[k]=x+y,A[k+i]=x-y;
                wnk=wnk*wn;
            }
        }
    }
    if(dft==1) return;
    for(int i=0;i<=len;++i) A[i].x/=len;
}

int main()
{
    n=read();
    for(int i=1;i<=n;++i) scanf("%lf",&a[i].x),b[n-i+1].x=a[i].x;
    for(int i=1;i<=n;++i) c[i].x=1.0/(1ll*i*i);
    while(len<=(n<<1)) ++bit,len<<=1;
    for(int i=0;i<len;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
    fft(a,1),fft(b,1),fft(c,1);
    for(int i=0;i<=len;++i) a[i]=a[i]*c[i],b[i]=b[i]*c[i];
    fft(a,-1),fft(b,-1);
    for(int i=1;i<=n;++i) printf("%.3lf
",a[i].x-b[n-i+1].x);
    return 0;
}
View Code

2194: 快速傅立叶之二

不会,抄的。 好像知道fft/卷积一拉子是干什么的了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
 
typedef long long LL;
 
inline int read()
{
    char c=getchar();int num=0,f=1;
    for(;!isdigit(c);c=getchar())
        f=c=='-'?-1:f;
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num*f;
}
 
const int N=4e5+5;
const double pi=acos(-1);
 
int n,bit,len=1,rev[N];
 
struct Complex
{
    double x,y;
    Complex(double a=0,double b=0){x=a,y=b;}
    Complex operator + (const Complex &A){return Complex(x+A.x,y+A.y);}
    Complex operator - (const Complex &A){return Complex(x-A.x,y-A.y);}
    Complex operator * (const Complex &A){return Complex(x*A.x-y*A.y,x*A.y+y*A.x);}
}a[N],b[N];
 
void fft(Complex *A,int dft)
{
    for(int i=0;i<len;++i)
        if(i<rev[i]) swap(A[i],A[rev[i]]);
    for(int i=1;i<len;i<<=1)
    {
        Complex wn(cos(pi/i),dft*sin(pi/i));
        for(int j=0,t=i<<1;j<len;j+=t)
        {
            Complex wnk(1,0);
            for(int k=j;k<i+j;++k)
            {
                Complex x=A[k],y=wnk*A[k+i];
                A[k]=x+y,A[k+i]=x-y;
                wnk=wnk*wn;
            }
        }
    }
    if(dft==1) return;
    for(int i=0;i<len;++i) A[i].x/=len;
}
 
int main()
{
    n=read();
    for(int i=0;i<n;++i)
    {
        a[n-i-1].x=read();
        b[i].x=read();
    }
    while(len<=(n<<1)) len<<=1,++bit;
    for(int i=0;i<len;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
    fft(a,1),fft(b,1);
    for(int i=0;i<=len;++i) a[i]=a[i]*b[i];
    fft(a,-1);
    for(int i=0;i<n;++i)
        printf("%d
",(int)(a[n-i-1].x+0.5));
    return 0;
}
View Code

3513: [MUTC2013]idiots

不会,抄的。还是不知道fft/卷积一拉子是干什么的。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
 
typedef long long LL;
 
inline int read()
{
    char c=getchar();int num=0,f=1;
    for(;!isdigit(c);c=getchar())
        f=c=='-'?-1:f;
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num*f;
}
 
const int N=4e5+5;
const double pi=acos(-1);
 
int n,bit,len=1,rev[N];
LL g[N],t[N];

struct Complex
{
    double x,y;
    Complex(double a=0,double b=0){x=a,y=b;}
    Complex operator + (const Complex &A){return Complex(x+A.x,y+A.y);}
    Complex operator - (const Complex &A){return Complex(x-A.x,y-A.y);}
    Complex operator * (const Complex &A){return Complex(x*A.x-y*A.y,x*A.y+y*A.x);}
}f[N];
 
void fft(Complex *A,int dft)
{
    for(int i=0;i<len;++i)
        if(i<rev[i]) swap(A[i],A[rev[i]]);
    for(int i=1;i<len;i<<=1)
    {
        Complex wn(cos(pi/i),dft*sin(pi/i));
        for(int j=0,t=i<<1;j<len;j+=t)
        {
            Complex wnk(1,0);
            for(int k=j;k<i+j;++k)
            {
                Complex x=A[k],y=wnk*A[k+i];
                A[k]=x+y,A[k+i]=x-y;
                wnk=wnk*wn;
            }
        }
    }
    if(dft==1) return;
    for(int i=0;i<=len;++i) A[i].x/=len;
}
 
int main()
{
    int T=read();
    while(T--)
    {
        memset(g,0,sizeof(g)),memset(t,0,sizeof(t));
        memset(f,0,sizeof(f));
        n=read();int mx=0;LL sum;
        for(int i=1,a;i<=n;++i)
        {
            a=read();mx=max(mx,a);
            --g[a<<1],++t[a],++f[a].x;
        }
        for(int i=mx;i;--i) t[i]+=t[i+1];
        mx<<=1,sum=1ll*n*(n-1)*(n-2)/6;
        len=1,bit=0;while(len<=mx) len<<=1,++bit;
        for(int i=0;i<=len;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
        fft(f,1);
        for(int i=0;i<=len;++i) f[i]=f[i]*f[i];
        fft(f,-1);
        for(int i=0;i<=len;++i) g[i]+=1ll*(f[i].x+0.5);
        LL ans=0;
        for(int i=0;i<=len;++i) ans+=(g[i]/2)*t[i];
        ans=sum-ans;
        printf("%.7lf
",1.0*ans/sum);
    }
    return 0;
}
View Code
 不会,抄的。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

typedef long long LL;

inline int read()
{
    char c=getchar();int num=0,f=1;
    for(;!isdigit(c);c=getchar())
        f=c=='-'?-1:f;
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num*f;
}

const int N=3e5+5;
const double pi=acos(-1);

int n,m,len=1,bit,rev[N];

struct Complex
{
    double x,y;
    Complex(double a=0,double b=0){x=a,y=b;}
    Complex operator + (const Complex &A){return Complex(x+A.x,y+A.y);}
    Complex operator - (const Complex &A){return Complex(x-A.x,y-A.y);}
    Complex operator * (const Complex &A){return Complex(x*A.x-y*A.y,x*A.y+y*A.x);}
}a[N],b[N];

void fft(Complex *A,int dft)
{
    for(int i=0;i<len;++i)
        if(i<rev[i]) swap(A[i],A[rev[i]]);
    for(int i=1;i<len;i<<=1)
    {
        Complex wn(cos(pi/i),dft*sin(pi/i));
        for(int j=0,t=i<<1;j<len;j+=t)
        {
            Complex wnk(1,0);
            for(int k=j;k<i+j;++k)
            {
                Complex x=A[k],y=wnk*A[k+i];
                A[k]=x+y,A[k+i]=x-y;
                wnk=wnk*wn;
            }
        }
    }
    if(dft==1) return;
    for(int i=0;i<=len;++i) A[i].x=A[i].x/len+0.5;
}

int main()
{
    n=read(),m=read();LL a1=0,a2=0,b1=0,b2=0;
    for(int i=1;i<=n;++i)
    {
        a[i].x=a[n+i].x=read();
        a1+=a[i].x*a[i].x,a2+=a[i].x;
    }
    for(int i=1;i<=n;++i)
    {
        b[n-i+1].x=read();
        b1+=b[n-i+1].x*b[n-i+1].x,b2+=b[n-i+1].x;
    }
    while(len<=(n*3)) len<<=1,++bit;
    for(int i=0;i<len;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
    fft(a,1),fft(b,1);
    for(int i=0;i<=len;++i) a[i]=a[i]*b[i];
    fft(a,-1);
    LL ans=1ll<<60,sum=ans;
    for(int j=-m;j<=m;++j) sum=min(sum,a1+b1+n*j*j+2ll*j*(a2-b2));
    for(int i=1;i<=n;++i) ans=min(ans,sum-2ll*(LL)a[n+i].x);
    cout<<ans;
    return 0;
}
View Code

真tm难啊

原文地址:https://www.cnblogs.com/lovewhy/p/10217235.html