LG3803 [template] polynomial multiplication (FFT)

P3803 [template] polynomial multiplication (FFT)

Note: Although this question to open 3s, but recommended that the program can finish within 1s, this question requires a certain degree of constant optimization.

Title Description

Given a polynomial of degree n F (x), and a m-order polynomial G (x).

Request the convolution F (x) and G (x) of.

Input and output formats

Input formats:

The first line of two positive integers n, m.

The next line n + 1 digits represented from low to high coefficient F (x) of.

The next line m + 1 digits represented from low to high coefficient G (x)) of.

Output formats:

Line n + m + 1 digits represented from low to high coefficient F (x) * G (x) of.

Sample input and output

Input Sample # 1: Copy
1 2
1 2
1 2 1
Output Sample # 1: Copy
1 4 5 2

Explanation

Ensure coefficient input is greater than or equal to 0 and less than or equal to 9.

To 100% of the data: $ n, m \ leq {10} ^ 6 $, a total of 20 data points, 2s.

Data have a gradient.

Space limitations: 256MB

Fast Fourier Transform Fast Fourier Transform (FFT)

All kinds of information are written in a very clear, there is nothing to say.

Then summed up with high precision, a small constant (portion) code, embodied in a binary butterfly operation and the flip.

Here I encapsulates the code, and then open TLE ...... O2 repeatedly post cards into the 3s.


#8
AC
2923ms/78800KB


9 # the
AC
2949ms / 81944KB

Then the output is -0 problem. Time complexity \ (O (n \ log n ) \)

#include<bits/stdc++.h>
#define il inline
#define co const
template<class T>T read(){
    T data=0,w=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
    for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
    return data*w;
}
template<class T>il T read(T&x) {return x=read<T>();}
typedef long long LL;
using namespace std;
typedef vector<complex<double> > polynomial;

co double PI=acos(-1);
void Fourier_Transform(polynomial&a,int inverse){
    int limit=a.size(),len=log2(limit);
     // bit reserval
    vector<int> bit_rev(limit);
    for(int i=0;i<limit;++i) bit_rev[i]=bit_rev[i>>1]>>1|(i&1)<<len-1;
    for(int i=0;i<limit;++i)if(i<bit_rev[i]) swap(a[i],a[bit_rev[i]]);
    // Butterfly diagram
    for(int step=1;step<limit;step<<=1){
        double alpha=inverse*PI/step;
        for(int k=0;k<step;++k){
            complex<double> omega_k=exp(complex<double>(0,alpha*k));
            for(int even_k=k;even_k<limit;even_k+=step<<1){
                int odd_k=even_k+step;
                complex<double> t=omega_k*a[odd_k];
                a[odd_k]=a[even_k]-t,a[even_k]+=t;
            }
        }
    }
    if(inverse==-1)for(int i=0;i<limit;++i) a[i]/=limit;
}

int main(){
//  freopen("LG3803.in","r",stdin),freopen("LG3803.out","w",stdout);
    int n=read<int>(),m=read<int>();
    polynomial a(n+1),b(m+1);
    for(int i=0;i<=n;++i) read(a[i].real());
    for(int i=0;i<=m;++i) read(b[i].real());
    int limit=1;
    while(limit<n+m+1) limit<<=1;
    a.resize(limit),b.resize(limit);
    Fourier_Transform(a,1),Fourier_Transform(b,1);
    for(int i=0;i<limit;++i) a[i]*=b[i];
    Fourier_Transform(a,-1);
    for(int i=0;i<=n+m;++i) printf("%.0lf ",a[i].real()+1e-9); // edit 1:-0
    return 0;
}

Guess you like

Origin www.cnblogs.com/autoint/p/11096321.html