BZOJ 2194

Title:
BZOJ 2194 BZOJ2194BZOJ2194


c i = ∑ j = i n − 1 a j b j − i ( 0 ≤ i ≤ n − 1 ) c_i=\sum_{j=i}^{n-1}a_jb_{j-i}\quad (0\le i\le n-1) ci=j=in1ajbji(0in1)

Idea:
put aj a_jajMapped to A n − 1 − j A_{n-1-j}An - 1 - j
c i = ∑ j = i n − 1 a j b j − i = ∑ j = i n − 1 A n − 1 − j b j − i 令 t = j − i = ∑ t = 0 n − 1 − i A n − 1 − i − t b t \begin{aligned} c_i&=\sum_{j=i}^{n-1}a_jb_{j-i}\\ &=\sum_{j=i}^{n-1}A_{n-1-j}b_{j-i}\quad 令t=j-i\\ &=\sum_{t=0}^{n-1-i}A_{n-1-i-t}b_t \end{aligned} ci=j=in1ajbji=j=in1An - 1 - jbjiLet t=ji=t=0n1iAn1itbt
Convolution FFT FFTF F T , pay attention to accuracy

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const double Pi=acos(-1.0);
const int N=300009;
struct com
{
    
    
    double x,y;
    com(double xx=0,double yy=0)
    {
    
    
        x=xx,y=yy;
    }
}a[N],aa[N],b[N],c[N],cc[N];
com operator + (com a,com b)
{
    
    
    return com(a.x+b.x,a.y+b.y);
}
com operator - (com a,com b)
{
    
    
    return com(a.x-b.x,a.y-b.y);
}
com operator * (com a,com b)
{
    
    
    return com(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
}
int n,m,bit=0,lim=1,r[N];
double sinn[N],coss[N];
void init()
{
    
    
    while(lim<=2*n-1)
        lim<<=1,bit++;
    for(int i=1;i<lim;i<<=1)
        sinn[i]=sin(Pi/i),coss[i]=cos(Pi/i);
    for(int i=0;i<lim;i++)
        r[i]=(r[i>>1]>>1)|((i&1)<<(bit-1));
}
void FFT(com *a,int type)
{
    
    
    for(int i=0;i<lim;i++)
        if(i<r[i])
        swap(a[i],a[r[i]]);
    for(int mid=1;mid<lim;mid<<=1)
    {
    
    
        com W(coss[mid],type*sinn[mid]);
        for(int r=mid<<1,j=0;j<lim;j+=r)
        {
    
    
            com e(1,0);
            for(int k=0;k<mid;k++,e=e*W)
            {
    
    
                com x=a[j+k],y=e*a[j+k+mid];
                a[j+k]=x+y,a[j+k+mid]=x-y;
            }
        }
    }
    if(type==-1)
        for(int i=0;i<lim;i++)
            a[i].x/=lim;
}
int main()
{
    
    
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%lf%lf",&a[n-1-i].x,&b[i].x);
    init();
    FFT(a,1),FFT(b,1);
    for(int i=0;i<lim;i++)
        c[i]=a[i]*b[i];
    FFT(c,-1);
    for(int i=0;i<n;i++)
    printf("%d\n",(int)(c[n-1-i].x+0.5));//注意精度
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_43520313/article/details/108720634