模板 NTT 快速数论变换

NTT裸模板,没什么好解释的

这种高深算法其实也没那么必要知道原理

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N (1<<17)+10
#define ll long long 
using namespace std;

ll inv3,invl;
int r[N];
ll A[N],B[N],C[N],mulwn[N],invwn[N];
char s1[N],s2[N];
const ll p=998244353;
ll qpow(ll x,ll y,ll mo){
    ll ans=1;
    while(y){
        if(y&1) ans=(ans*x)%mo;
        x=(x*x)%mo,y>>=1;
    }return ans;
}
void pre(int len,int l)
{
    inv3=qpow(3,p-2,p),invl=qpow(len,p-2,p);
    for(int i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    for(ll i=1;i<=len;i<<=1) mulwn[i]=qpow(3,(p-1)/i,p);
    for(ll i=1;i<=len;i<<=1) invwn[i]=qpow(mulwn[i],p-2,p);
}
void NTT(ll *a,int len,int type)
{
    for(int i=0;i<len;i++)
        if(i<r[i]) swap(a[i],a[r[i]]);
    for(int k=2;k<=len;k<<=1)
    {
        ll wn=(type>0)?mulwn[k]:invwn[k];
        int mid=k>>1;
        for(int i=0;i<len;i+=k)
        {
            ll w=1;
            for(int j=0;j<mid;j++,w=(w*wn)%p)
            {
                ll t=(w*a[i+j+mid])%p;
                a[i+j+mid]=(a[i+j]-t+p)%p;
                a[i+j]=(a[i+j]+t)%p;
            }
        }
    }
    if(type==-1)
        for(int i=0;i<len;i++)
            a[i]=(a[i]*invl)%p;
}
void NTT_main(ll *a,ll *b,ll *c,int len,int l)
{
    NTT(a,len,1);NTT(b,len,1);
    for(int i=0;i<len;i++) c[i]=(a[i]*b[i])%p;
    NTT(c,len,-1);
}

int main()
{
    int n,len=1,l=0;scanf("%d",&n);
    scanf("%s",s1),scanf("%s",s2);
    for(int i=0;i<n;i++) A[n-i-1]=s1[i]-'0';
    for(int i=0;i<n;i++) B[n-i-1]=s2[i]-'0';
    while(len<n+n) len<<=1,l++;
    pre(len,l);
    NTT_main(A,B,C,len,l);
    for(int i=0;i<len;i++)
        if(C[i]>9) C[i+1]+=C[i]/10,C[i]%=10;
    int j=len;
    while(C[j]==0) j--;
    while(j>-1) printf("%lld",C[j]),j--;
    puts("");
    return 0;
}


 

猜你喜欢

转载自blog.csdn.net/guapisolo/article/details/82771397