[Template] A * B Problem upgraded version (FFT Fast Fourier)

Title Description

Given two $ $ n-digit decimal numbers x and y, find x * y (see Luo Valley P1919 )

analysis

Assumptions have learned FFT / NTT.

Polynomial multiplication except special cases precision multiplication, when corresponding to $ x = 10 $.

For example n = 3, * 111 123 seek

$$ 123 = x ^ 2 + 2x + 3 $$

$$111 = x^2 + x +1$$

$$\begin{aligned}123 * 111 &= (x^2 + 2x + 3)(x^2 + x +1)\\  &= x^4 + 3x^3 + 6x^2 + 5x + 3\\  &= 13653\end{aligned}$$

Code:

#include<bits/stdc++.h>
#define rg register
using namespace std;

typedef long long ll;
const int mod=998244353,g=3;
const int maxn = 6e4 + 10;

inline int qpow(int x,int k)
{
    int ans=1;
    while(k)
    {
        if(k&1)
            ans=(ll)ans*x%mod;
        x=(ll)x*x%mod,k>>=1;
    }
    return ans;
}

inline int module(int x,int y)
{
    x+=y;
    if(x>=mod)
        x-=mod;
    return x;
}

int rev[4*maxn];
inline void NTT(int*t,int lim,int type)
{
    for(rg int i=0;i<lim;++i)
        if(i<rev[i])
            swap(t[i],t[rev[i]]);
    for(rg int i=1;i<lim;i<<=1)
    {
        int gn=qpow(g,(mod-1)/(i<<1));
        if(type==-1)
            gn=qpow(gn,mod-2);
        for(rg int j=0;j<lim;j+=(i<<1))
        {
            int gi=1;
            for(rg int k=0;k<i;++k,gi=(ll)gi*gn%mod)
            {
                int x=t[j+k],y=(ll)gi*t[j+i+k]%mod;
                t[j+k]=module(x,y);
                t[j+i+k]=module(x,mod-y);
            }
        }
    }
    if(type==-1)
    {
        int inv=qpow(lim,mod-2);
        for(rg int i=0;i<lim;++i)
            t[i]=(ll)t[i]*inv%mod;
    }
}

int X[4*maxn],Y[4* MAXN]; 
inline void MUL ( int * X, int * Y, int n-, int m) 
{ 
    Memset (X-, 0 , the sizeof (X-)); 
    Memset (the Y, 0 , the sizeof (the Y));
     int Lim = . 1 , L = 0 ;   // L = 0 must be written, the default value is a local variable may not 0 
    the while (Lim <= n-m +) = Lim << . 1 , L ++;    // Lim greater than (n + m) of power of 2, it is up to 4 times the space 
    for ( int I = 0 ; I <Lim; I ++) Rev [I] = (Rev [I >> . 1] >> 1) | ((i & 1) << (L - 1));
    for(rg int i=0;i<lim;++i) X[i]=x[i],Y[i]=y[i];
    NTT(X,lim,1);
    NTT(Y,lim,1);
    for(rg int i=0;i<lim;++i) X[i]=(ll)X[i]*Y[i]%mod;
    NTT(X,lim,-1);
    for(rg int i=0;i<lim;++i) x[i]=X[i];
}


int n;
int a[4*maxn], b[4*maxn];
char s[maxn];

int main()
{
    scanf("%d", &n);
    scanf("%s", s);
    for(int i = 0;i < n;i++) a[i] = s[n-1-i] - '0';
    scanf("%s", s);
    for(int i = 0;i < n;i++)  b[i] = s[n-1-i] - '0';
    mul(a, b, n, n);

//    for(int i = 0;i < 2*n;i++)  printf("%d ", a[i]);
//    printf("\n");

    int tmp = 0;    //进位
    for(int i = 0;i < 2*n;i++)  //
    {
        a[i] = a[i] + tmp;
        tmp = a[i] / 10;
        a[i] = a[i] % 10;

    }

//    for(int i = 0;i < 2*n;i++)  printf("%d ", a[i]);
//    printf("\n");

    bool flag = true;
    for(int I = 2 * n-; I> = 0 ; i--)   // reverse order output, removing the leading zeros 
    {
         IF (In Flag && A [I] == 0 )   Continue ; 
         the printf ( " % D " , A [I] ); 
         In Flag = to false ; 
    } 

    return  0 ; 
}

 

Guess you like

Origin www.cnblogs.com/lfri/p/11242183.html