BZOJ 2194

タイトル:
BZOJ 2194 BZOJ2194B Z O J 2 1 9 4

求位
= ∑ j = in − 1 ajbj − i(0≤i≤n− 1)c_i = \ sum_ {j = i} ^ {n-1} a_jb_ {ji} \ quad(0 \ le i \ le n -1)c=j = iN - 1AJbJ - I0n1

アイデア:
置くa_j AJAJA n − 1 − j A_ {n-1-j}にマッピングAn - 1 - j
ci = ∑ j = in − 1 ajbj − i = ∑ j = in − 1 A n − 1 − jbj −i令t = j − i = ∑ t = 0 n − 1 − i A n − 1 − i − tbt \ begin {aligned} c_i&= \ sum_ {j = i} ^ {n-1} a_jb_ {ji} \\&= \ sum_ {j = i} ^ {n-1} A_ {n-1-j} b_ {ji} \ quad令t = ji \\&= \ sum_ {t = 0} ^ {n-1-i} A_ {n-1-it} b_t \ end {aligned} c=j = iN - 1AJbJ - I=j = iN - 1An - 1 - jbJ - Itをしましょう=j=t = 0N - 1 - IAN - 1 - I -トンbトン
コンボリューションFFT FFTF F T、精度に注意してください

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

おすすめ

転載: blog.csdn.net/qq_43520313/article/details/108720634