Luogu P1919 【模板】A*B Problem升级版(FFT快速傅里叶)

题目大意

给出两个 n n 10 10 进制整数 x x y y ,求 x×y x × y

数据范围

1n6×104 1 ⩽ n ⩽ 6 × 10 4

题解

首先,如果你的比赛可以用Python的话,我不拦你用input(),print(int(input())*int(input()))
其次,如果你不想练FFT的话,你也可以大方地用高精压8位卡过去。但就不要再往下看了。
考虑把 x x y y 分解。
即表示成 x=ai×10i,y=bi×10i x = ∑ a i × 10 i , y = ∑ b i × 10 i
x×y=(ai×10i)(bi×10i) x × y = ( ∑ a i × 10 i ) ( ∑ b i × 10 i )
即多项式乘法,转换为他们系数向量的卷积,即 a⃗  a → b⃗  b → 的卷积。
然后套FFT即可,最后注意前导0。

代码

Emmm……不要在意函数名。

#include
using namespace std;
const int maxn=131172;
const double Pi=acos(-1.0);
struct complex {
    double x,y;
    complex (double xx=0,double yy=0) {x=xx,y=yy;}
    complex operator+(complex b) {return complex(x+b.x,y+b.y);}
    complex operator-(complex b) {return complex(x-b.x,y-b.y);}
    complex operator*(complex b) {return complex(x*b.x-y*b.y , x*b.y+y*b.x);}
} a[maxn],b[maxn];
int N,M,c[maxn];
int l,r[maxn];
int limit=1;
void fast_fast_tle(complex *A,int type) {
    for(int i=0; i<=limit; i++)
        if(ifor(int mid=1; mid1) {
        complex Wn( cos(Pi/mid) , type*sin(Pi/mid) );
        for(int R=mid<<1,j=0; jcomplex w(1,0);
            for(int k=0; kcomplex x=A[j+k],y=w*A[j+mid+k];
                A[j+k]=x+y;
                A[j+mid+k]=x-y;
            }
        }
    }
}
inline char nc() {
    static char buf[1000000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
#define nc getchar
inline int read(int &sum) {
    char ch=nc();
    sum=0;
    while(!(ch>='0'&&ch<='9'))
        ch=nc();
    while(ch>='0'&&ch<='9')
        sum=(sum<<3)+(sum<<1)+(ch^48),ch=nc();
    return sum;
}
inline int read_ch(void) {
    int t=nc();
    while(t<'0'||t>'9')
        t=nc();
    return t-'0';
}
int main() {
    read(N);M=--N;
    for(int i=0; i<=N; i++)
        a[i].x=read_ch();
    for(int i=0; i<=M; i++)
        b[i].x=read_ch();
    while(limit<=N+M) limit<<=1,l++;
    for(int i=0; i>1]>>1)|((i&1)<<(l-1));
    fast_fast_tle(a,1);
    fast_fast_tle(b,1);
    for(int i=0; i1);
    for(int i=0; i<=N+M; i++)
        c[i]=a[i].x/limit+0.5;//考虑精度误差
    for(int i=N+M;i>0;i--)//进位
        if(c[i]>=10){
            c[i-1]+=c[i]/10;
            c[i]%=10;
        }
    bool tf=false;
    for(int i=0; i<=N+M; i++){
        if(tf==false&&c[i]==0)
            continue;
        tf=true;
        printf("%d",c[i]);
    }
    return 0;
}

你可能感兴趣的:(FFT)